diff --git a/.gitignore b/.gitignore index e94087e29..1f1561475 100644 --- a/.gitignore +++ b/.gitignore @@ -66,6 +66,7 @@ CCache/ccache_swig_config.h CCache/config.h CCache/config.log CCache/config.status +CCache/config_win32.h Examples/Makefile Examples/d/example.mk Examples/guile/Makefile @@ -85,6 +86,8 @@ swig.spec # Build Artifacts .dirstamp CCache/ccache-swig +CCache/ccache-swig.1 +CCache/web/ccache-swig-man.html Lib/swigwarn.swg Source/CParse/parser.c Source/CParse/parser.h @@ -149,11 +152,24 @@ Examples/guile/*/my-guile Examples/test-suite/java/*/ Examples/java/*/*.java !Examples/java/*/runme.java +Examples/java/doxygen/javadocs # Javascript Examples/test-suite/javascript/*/ *.gyp +# OCaml +Examples/test-suite/ocaml/*.ml* +Examples/test-suite/ocaml/*.cm* +Examples/test-suite/ocaml/*_runme +!Examples/test-suite/ocaml/*runme.ml +Examples/ocaml/**/example.ml* +Examples/ocaml/**/runme +Examples/ocaml/**/runme_top +Examples/ocaml/**/*.cm* +Examples/ocaml/**/swig.ml* +Examples/ocaml/**/swigp4.ml + # Octave swigexample*.oct Examples/test-suite/octave/*.oct @@ -177,11 +193,16 @@ Examples/php/*/example.php /__pycache__/ Examples/test-suite/python/*.py !Examples/test-suite/python/*runme.py -Examples/python/*/example.py Examples/python/**/bar.py Examples/python/**/base.py +Examples/python/**/example.py Examples/python/**/foo.py +Examples/python/**/robin.py +Examples/python/**/runme3.py Examples/python/**/spam.py +Examples/python/import_packages/module_is_init/pkg1/__init__.py +Examples/python/import_packages/namespace_pkg/path4.zip +Examples/python/doxygen/example.html # R Examples/test-suite/r/*.R diff --git a/.travis.yml b/.travis.yml index ac97dc6b5..c9cbd7862 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,155 +4,404 @@ matrix: - compiler: clang os: linux env: SWIGLANG= + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG= - - os: linux - env: SWIGLANG= SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required - dist: trusty + dist: xenial - os: linux - env: SWIGLANG= SWIG_CC=gcc-6 SWIG_CXX=g++-6 + env: SWIGLANG= GCC=4.4 sudo: required - dist: trusty + dist: xenial + - os: linux + env: SWIGLANG= GCC=4.6 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG= GCC=4.7 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG= GCC=4.8 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG= GCC=4.9 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG= GCC=6 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG= GCC=7 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG= GCC=8 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG= GCC=9 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=csharp + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=d - - compiler: gcc - os: linux - env: SWIGLANG=go - - compiler: gcc - os: linux - env: SWIGLANG=go VER=1.5 sudo: required - dist: trusty + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=go VER=1.3 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=go VER=1.8 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=go VER=1.12 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=guile + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=java + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=javascript ENGINE=node + env: SWIGLANG=javascript ENGINE=node VER=0.10 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=javascript ENGINE=node VER=4 CPP11=1 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=javascript ENGINE=node VER=6 CPP11=1 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=javascript ENGINE=node VER=8 CPP11=1 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=javascript ENGINE=node VER=10 CPP11=1 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=javascript ENGINE=jsc + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=javascript ENGINE=v8 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=lua + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=lua VER=5.3 sudo: required - dist: trusty + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=octave SWIGJOBS=-j2 # 3.2 + env: SWIGLANG=mzscheme + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=octave SWIGJOBS=-j2 VER=3.8 + env: SWIGLANG=ocaml + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=octave SWIGJOBS=-j2 VER=4.0 + env: SWIGLANG=octave SWIGJOBS=-j2 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=perl5 + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=php + env: SWIGLANG=php VER=7.0 + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=python VER=2.4 + env: SWIGLANG=php VER=7.1 + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=python VER=2.5 + env: SWIGLANG=php VER=7.2 + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=python VER=2.6 + env: SWIGLANG=php VER=7.3 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=python # 2.7 + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=python PY3=3 # 3.2 + env: SWIGLANG=python PY3=3 VER=3.2 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=python PY3=3 VER=3.3 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=python PY3=3 VER=3.4 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=python PY3=3 VER=3.5 + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin VER=2.6 + env: SWIGLANG=python PY3=3 VER=3.6 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=python PY3=3 VER=3.7 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=python SWIG_FEATURES=-builtin + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 + env: SWIGLANG=python SWIG_FEATURES="-builtin -O" + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=python SWIG_FEATURES=-builtin GCC=6 CPP11=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=python SWIG_FEATURES=-builtin GCC=6 CPP11=1 PY3=3 VER=3.7 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.4 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.5 + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.5 SWIGOPTPY3= + env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.7 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=python SWIG_FEATURES="-builtin -O" PY3=3 VER=3.7 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.7 SWIGOPTPY3= + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=python SWIG_FEATURES=-O + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=python SWIG_FEATURES=-classic + env: SWIGLANG=python SWIG_FEATURES=-O PY3=3 VER=3.7 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=r + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=ruby + env: SWIGLANG=ruby VER=1.9 + sudo: required + dist: xenial - compiler: gcc os: linux - env: SWIGLANG=ruby VER=2.3.0 + env: SWIGLANG=ruby VER=2.0 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=ruby VER=2.1 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=ruby VER=2.2 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=ruby VER=2.3 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=ruby VER=2.4 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=ruby VER=2.5 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=ruby VER=2.6 + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=scilab + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=tcl + sudo: required + dist: xenial - os: linux - env: SWIGLANG=csharp SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 + env: SWIGLANG=csharp CPP11=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=go VER=1.6 CPP11=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=java CPP11=1 + sudo: required + dist: xenial + - compiler: gcc + os: linux + env: SWIGLANG=octave SWIGJOBS=-j2 VER=4.4 CPP11=1 sudo: required dist: trusty - os: linux - env: SWIGLANG=java SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 + env: SWIGLANG=python CPP11=1 sudo: required - dist: trusty + dist: xenial - os: linux - env: SWIGLANG=python SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 + env: SWIGLANG=r CPP11=1 # Note: making 'R CMD SHLIB' use a different compiler is non-trivial sudo: required - dist: trusty + dist: xenial - os: linux - env: SWIGLANG=csharp SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 + env: SWIGLANG=ruby CPP11=1 sudo: required - dist: trusty + dist: xenial - os: linux - env: SWIGLANG=java SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 + env: SWIGLANG=tcl CPP11=1 sudo: required - dist: trusty + dist: xenial - os: linux - env: SWIGLANG=python SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 + env: SWIGLANG=csharp GCC=6 CPP14=1 sudo: required - dist: trusty - - os: osx - env: SWIGLANG= SWIG_CC=gcc-4.2 SWIG_CXX=g++-4.2 + dist: xenial + - os: linux + env: SWIGLANG=go VER=1.6 GCC=6 CPP14=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=java GCC=6 CPP14=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=python GCC=6 CPP14=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=ruby GCC=6 CPP14=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=tcl GCC=6 CPP14=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=java GCC=7 CPP14=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=python GCC=7 CPP14=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=csharp GCC=8 CPP17=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=java GCC=8 CPP17=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=python GCC=8 CPP17=1 PY3=3 VER=3.7 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=csharp GCC=9 CPP17=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=java GCC=9 CPP17=1 + sudo: required + dist: xenial + - os: linux + env: SWIGLANG=python GCC=9 CPP17=1 PY3=3 VER=3.7 + sudo: required + dist: xenial + - compiler: gcc + os: osx + env: SWIGLANG= - compiler: clang os: osx env: SWIGLANG= @@ -173,10 +422,10 @@ matrix: env: SWIGLANG=lua - compiler: clang os: osx - env: SWIGLANG=perl5 + env: SWIGLANG=octave SWIGJOBS=-j2 - compiler: clang os: osx - env: SWIGLANG=php + env: SWIGLANG=perl5 - compiler: clang os: osx env: SWIGLANG=python @@ -189,35 +438,54 @@ matrix: - compiler: clang os: osx env: SWIGLANG=tcl + - compiler: clang + os: osx + env: SWIGLANG=java CPP17=1 + osx_image: xcode10.2 + - compiler: clang + os: osx + env: SWIGLANG=python PY3=3 CPP17=1 + osx_image: xcode10.2 allow_failures: - # Lots of failing tests currently + # seg fault in director_basic testcase + - compiler: gcc + os: linux + env: SWIGLANG=php VER=7.2 + sudo: required + dist: xenial + # Sometimes hits the Travis 50 minute time limit + - compiler: clang + os: osx + env: SWIGLANG=octave SWIGJOBS=-j2 + # Experimental languages + - compiler: gcc + os: linux + env: SWIGLANG=mzscheme + sudo: required + dist: xenial - compiler: gcc os: linux env: SWIGLANG=ocaml - # Not quite working yet - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-O + sudo: required + dist: xenial + before_install: - date -u - uname -a - if test "$TRAVIS_OS_NAME" = "linux"; then lscpu && cat /proc/cpuinfo | grep "model name" && cat /proc/meminfo | grep MemTotal; fi - if test "$TRAVIS_OS_NAME" = "osx"; then sysctl -a | grep brand_string; fi - # Travis overrides CC environment with compiler predefined values - - if test -n "$SWIG_CC"; then export CC="$SWIG_CC"; fi - - if test -n "$SWIG_CXX"; then export CXX="$SWIG_CXX"; fi + # Travis overrides CC environment with compiler predefined values + - if test -n "$GCC"; then export CC="gcc-$GCC" && export CXX="g++-$GCC"; fi install: - if test "$TRAVIS_OS_NAME" = "linux"; then source Tools/travis-linux-install.sh; fi - if test "$TRAVIS_OS_NAME" = "osx"; then source Tools/travis-osx-install.sh; fi - - if test -n "$CPP11"; then CONFIGOPTS+=(--enable-cpp11-testing --without-maximum-compile-warnings "CXXFLAGS=-std=c++11 -Wall -Wextra" "CFLAGS=-std=c11 -Wall -Wextra") && export CSTD=c11 && export CPPSTD=c++11; fi - - if test -n "$CPP14"; then CONFIGOPTS+=(--enable-cpp11-testing --without-maximum-compile-warnings "CXXFLAGS=-std=c++14 -Wall -Wextra" "CFLAGS=-std=c11 -Wall -Wextra") && export CSTD=c11 && export CPPSTD=c++14; fi - - ls -la $(which $CC) - - ls -la $(which $CXX) - - $CC --version - - $CXX --version + - ls -la $(which $CC) $(which $CXX) && $CC --version && $CXX --version script: - echo 'Configuring...' && echo -en 'travis_fold:start:script.1\\r' + - if test -n "$CPP11"; then CONFIGOPTS+=(--enable-cpp11-testing --without-maximum-compile-warnings "CXXFLAGS=-std=c++11 -Wall -Wextra" "CFLAGS=-std=c11 -Wall -Wextra") && export CSTD=c11 && export CPPSTD=c++11; fi + - if test -n "$CPP14"; then CONFIGOPTS+=(--enable-cpp11-testing --without-maximum-compile-warnings "CXXFLAGS=-std=c++14 -Wall -Wextra" "CFLAGS=-std=c11 -Wall -Wextra") && export CSTD=c11 && export CPPSTD=c++14; fi + - if test -n "$CPP17"; then CONFIGOPTS+=(--enable-cpp11-testing --without-maximum-compile-warnings "CXXFLAGS=-std=c++17 -Wall -Wextra" "CFLAGS=-std=c17 -Wall -Wextra") && export CSTD=c17 && export CPPSTD=c++17; fi - if test -n "$SWIGLANG"; then CONFIGOPTS+=(--without-alllang --with-$WITHLANG); fi - echo "${CONFIGOPTS[@]}" - ./autogen.sh && mkdir -p build/build && cd build/build && ../../configure "${CONFIGOPTS[@]}" @@ -239,6 +507,3 @@ script: - echo 'Cleaning...' && echo -en 'travis_fold:start:script.3\\r' - make check-maintainer-clean && ../../configure $CONFIGOPTS - echo -en 'travis_fold:end:script.3\\r' -branches: - only: - - master diff --git a/ANNOUNCE b/ANNOUNCE index 53c5bbc59..b83921cc4 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,8 +1,8 @@ -*** ANNOUNCE: SWIG 3.0.11 (in progress) *** +*** ANNOUNCE: SWIG 4.0.1 (in progress) *** http://www.swig.org -We're pleased to announce SWIG-3.0.11, the latest SWIG release. +We're pleased to announce SWIG-4.0.1, the latest SWIG release. What is SWIG? ============= @@ -10,13 +10,11 @@ What is SWIG? SWIG is a software development tool that reads C/C++ header files and generates the wrapper code needed to make C and C++ code accessible from other programming languages including Perl, Python, Tcl, Ruby, -PHP, C#, Go, Java, Javascript, Lua, Scheme (Guile, MzScheme, CHICKEN), -D, Ocaml, Pike, Modula-3, Octave, R, Scilab, Common Lisp (CLISP, -Allegro CL, CFFI, UFFI). SWIG can also export its parse tree in -the form of XML and Lisp s-expressions. Major applications of SWIG -include generation of scripting language extension modules, rapid -prototyping, testing, and user interface development for large -C/C++ systems. +PHP, C#, Go, Java, Javascript, Lua, Scheme (Guile, MzScheme), D, +Ocaml, Octave, R, Scilab. SWIG can also export its parse tree in +the form of XML. Major applications of SWIG include generation of +scripting language extension modules, rapid prototyping, testing, +and user interface development for large C/C++ systems. Release Notes ============= @@ -27,11 +25,11 @@ Availability ============ The release is available for download on Sourceforge at - http://prdownloads.sourceforge.net/swig/swig-3.0.11.tar.gz + http://prdownloads.sourceforge.net/swig/swig-4.0.1.tar.gz A Windows version is also available at - http://prdownloads.sourceforge.net/swig/swigwin-3.0.11.zip + http://prdownloads.sourceforge.net/swig/swigwin-4.0.1.zip Please report problems with this release to the swig-devel mailing list, details at http://www.swig.org/mail.html. diff --git a/CCache/Makefile.in b/CCache/Makefile.in index 67fd3f363..d1bb8c526 100644 --- a/CCache/Makefile.in +++ b/CCache/Makefile.in @@ -8,6 +8,7 @@ bindir=@bindir@ mandir=@mandir@ INSTALLCMD=@INSTALL@ PACKAGE_NAME=@PACKAGE_NAME@ +PROGRAM_NAME=@PROGRAM_NAME@ # Soft link test can be skipped on systems that don't support soft linking NOSOFTLINKSTEST= @@ -17,13 +18,10 @@ SWIG=swig SWIG_LIB=../$(srcdir)/../Lib EXEEXT=@EXEEXT@ -# Use standard autoconf approach to transform executable name using --program-prefix and --program-suffix -transform = @program_transform_name@ - LIBS= @LIBS@ OBJS= ccache.o mdfour.o hash.o execute.o util.o args.o stats.o \ cleanup.o snprintf.o unify.o -HEADERS = ccache.h mdfour.h +HEADERS = ccache.h mdfour.h config.h config_win32.h all: $(PACKAGE_NAME)$(EXEEXT) @@ -32,7 +30,7 @@ Makefile: $(srcdir)/Makefile.in ./config.status $(SHELL) ./config.status # Note that HTML documentation is actually generated and used from the main SWIG documentation Makefile -docs: $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/ccache-man.html +docs: $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/$(PACKAGE_NAME)-man.html $(PACKAGE_NAME)$(EXEEXT): $(OBJS) $(HEADERS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) @@ -40,40 +38,43 @@ $(PACKAGE_NAME)$(EXEEXT): $(OBJS) $(HEADERS) $(srcdir)/$(PACKAGE_NAME).1: $(srcdir)/ccache.yo -yodl2man -o $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/ccache.yo -$(srcdir)/web/ccache-man.html: $(srcdir)/ccache.yo - yodl2html -o $(srcdir)/web/ccache-man.html $(srcdir)/ccache.yo +$(srcdir)/web/$(PACKAGE_NAME)-man.html: $(srcdir)/ccache.yo + yodl2html -o $(srcdir)/web/$(PACKAGE_NAME)-man.html $(srcdir)/ccache.yo install: $(PACKAGE_NAME)$(EXEEXT) @echo "Installing $(PACKAGE_NAME)" - @echo "Installing $(DESTDIR)${bindir}/`echo $(PACKAGE_NAME) | sed '$(transform)'`$(EXEEXT)" + @echo "Installing $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT)" ${INSTALLCMD} -d $(DESTDIR)${bindir} - ${INSTALLCMD} -m 755 $(PACKAGE_NAME)$(EXEEXT) $(DESTDIR)${bindir}/`echo $(PACKAGE_NAME) | sed '$(transform)'`$(EXEEXT) + ${INSTALLCMD} -m 755 $(PACKAGE_NAME)$(EXEEXT) $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT) install-docs: $(srcdir)/$(PACKAGE_NAME).1 - @echo "Installing $(DESTDIR)${mandir}/man1/`echo $(PACKAGE_NAME) | sed '$(transform)'`.1" + @echo "Installing $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1" ${INSTALLCMD} -d $(DESTDIR)${mandir}/man1 - ${INSTALLCMD} -m 644 $(srcdir)/$(PACKAGE_NAME).1 $(DESTDIR)${mandir}/man1/`echo $(PACKAGE_NAME) | sed '$(transform)'`.1 + ${INSTALLCMD} -m 644 $(srcdir)/$(PACKAGE_NAME).1 $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1 uninstall: $(PACKAGE_NAME)$(EXEEXT) - rm -f $(DESTDIR)${bindir}/`echo $(PACKAGE_NAME) | sed '$(transform)'`$(EXEEXT) + rm -f $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT) uninstall-docs: $(srcdir)/$(PACKAGE_NAME).1 - rm -f $(DESTDIR)${mandir}/man1/`echo $(PACKAGE_NAME) | sed '$(transform)'`.1 + rm -f $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1 -clean: +clean: clean-docs /bin/rm -f $(OBJS) *~ $(PACKAGE_NAME)$(EXEEXT) +clean-docs: + rm -f $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/$(PACKAGE_NAME)-man.html + test: test.sh - SWIG_LIB='$(SWIG_LIB)' PATH=../..:$$PATH SWIG='$(SWIG)' CC='$(CC)' NOSOFTLINKSTEST='$(NOSOFTLINKSTEST)' $(srcdir)/test.sh + SWIG_LIB='$(SWIG_LIB)' PATH=../..:$$PATH SWIG='$(SWIG)' CC='$(CC)' NOSOFTLINKSTEST='$(NOSOFTLINKSTEST)' CCACHE='../$(PACKAGE_NAME)' CCACHE_PROG=$(PROGRAM_NAME) $(srcdir)/test.sh check: test distclean: clean - /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status ccache_swig_config.h + /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status ccache_swig_config.h config_win32.h /bin/rm -rf autom4te.cache maintainer-clean: distclean - /bin/rm -f $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/ccache-man.html + /bin/rm -f $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/$(PACKAGE_NAME)-man.html # FIXME: To fix this, test.sh needs to be able to take ccache from the diff --git a/CCache/ccache.h b/CCache/ccache.h index a79d88322..25e786496 100644 --- a/CCache/ccache.h +++ b/CCache/ccache.h @@ -6,7 +6,7 @@ #include "config.h" #else #include -#define PACKAGE_NAME "ccache-swig.exe" +#include "config_win32.h" #endif #include @@ -51,7 +51,7 @@ #define STATUS_FATAL 4 #define STATUS_NOCACHE 5 -#define MYNAME PACKAGE_NAME +#define MYNAME PROGRAM_NAME #define LIMIT_MULTIPLE 0.8 diff --git a/CCache/config_win32.h.in b/CCache/config_win32.h.in new file mode 100644 index 000000000..2d5ab97e3 --- /dev/null +++ b/CCache/config_win32.h.in @@ -0,0 +1,3 @@ +#if !defined(PROGRAM_NAME) +#define PROGRAM_NAME "@PROGRAM_NAME@.exe" +#endif diff --git a/CCache/configure.ac b/CCache/configure.ac index dfbf86dbc..e1c761860 100644 --- a/CCache/configure.ac +++ b/CCache/configure.ac @@ -7,6 +7,7 @@ AC_CONFIG_SRCDIR([ccache.h]) AC_MSG_NOTICE([Configuring ccache]) AC_CONFIG_HEADER(config.h) +AC_CONFIG_FILES([config_win32.h]) dnl Checks for programs. AC_PROG_CC @@ -14,6 +15,20 @@ AC_PROG_CPP AC_PROG_INSTALL AC_ARG_PROGRAM # for program_transform_name +AC_SUBST(PROGRAM_NAME) +if test "x$program_prefix" != "xNONE" -a "x$program_prefix" != "x" +then + PROGRAM_NAME="$program_prefix$PACKAGE_NAME" +else + PROGRAM_NAME="$PACKAGE_NAME" +fi +if test "x$program_suffix" != "xNONE" -a "x$program_suffix" != "x" +then + PROGRAM_NAME="$PROGRAM_NAME$program_suffix" +fi + +AC_DEFINE_UNQUOTED(PROGRAM_NAME, "$PROGRAM_NAME", [Define my program name]) + AC_DEFINE([_GNU_SOURCE], 1, [Define _GNU_SOURCE so that we get all necessary prototypes]) diff --git a/CCache/snprintf.c b/CCache/snprintf.c index 32187c1a5..9bf8a817b 100644 --- a/CCache/snprintf.c +++ b/CCache/snprintf.c @@ -292,6 +292,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args break; case 'X': flags |= DP_F_UP; + /* FALLTHROUGH */ case 'x': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) @@ -314,6 +315,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args break; case 'E': flags |= DP_F_UP; + /* FALLTHROUGH */ case 'e': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); @@ -322,6 +324,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args break; case 'G': flags |= DP_F_UP; + /* FALLTHROUGH */ case 'g': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); diff --git a/CCache/test.sh b/CCache/test.sh index 438e782cd..3c44e859c 100755 --- a/CCache/test.sh +++ b/CCache/test.sh @@ -20,7 +20,12 @@ fi PATH="`echo $PATH | \ sed -e 's!:/usr\(/local\)*/lib\([0-9]\)*/ccache\(/\)*!!g'`" -CCACHE=../ccache-swig +if test -n "$CCACHE"; then + CCACHE="$CCACHE" +else + CCACHE=../ccache-swig +fi + TESTDIR=test.$$ test_failed() { @@ -406,6 +411,10 @@ swigtests() { # main program rm -rf $TESTDIR mkdir $TESTDIR +if test -n "$CCACHE_PROG"; then + ln -s $CCACHE $TESTDIR/$CCACHE_PROG + CCACHE=./$CCACHE_PROG +fi cd $TESTDIR || exit 1 unset CCACHE_DIR @@ -442,14 +451,16 @@ swigtests if test -z "$NOSOFTLINKSTEST"; then testsuite="link" - ln -s $CCACHE $COMPILER - CCACHE_COMPILE="./$COMPILER" + compilername=`basename $COMPILER` + ln -s $CCACHE ./$compilername + CCACHE_COMPILE="./$compilername" basetests - rm "./$COMPILER" - ln -s $CCACHE $SWIG - CCACHE_COMPILE="./$SWIG" + rm "./$compilername" + compilername=`basename $SWIG` + ln -s $CCACHE ./$compilername + CCACHE_COMPILE="./$compilername" swigtests - rm "./$SWIG" + rm "./$compilername" else echo "skipping testsuite link" fi diff --git a/CHANGES b/CHANGES index 0146ac7ac..7fd6b6da2 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,1985 @@ SWIG (Simplified Wrapper and Interface Generator) See the CHANGES.current file for changes in the current version. See the RELEASENOTES file for a summary of changes in each release. +Issue # numbers mentioned below can be found on Github. For more details, add +the issue number to the end of the URL: https://github.com/swig/swig/issues/ + +Version 4.0.0 (27 Apr 2019) +=========================== + +2019-04-24: vadz + #1517 Fix crash if "@return" Doxygen tag was used on a node without any return type. + +2019-04-24: vadz + #1515 Fix parsing of enums with trailing comma when using -doxygen. + +2019-04-19: ianlancetaylor + [Go] #1055 When generating Go code, make -cgo the default. Add new -no-cgo option + to disable the default. + +2019-04-19: pbecherer + [Tcl] #1508 Fix Visual Studio 2015 and later compilation errors due to snprintf macro + definition. + +2019-04-09: wsfulton + [C#] Fix FxCop warning CA2002 in SWIGPendingException - a lock on a reference of + type 'Type'. + +2019-03-30: wsfulton + [Java, D] Add the parameters typemap attribute to the javadestruct, + javadestruct_derived, ddispose, ddispose_derived typemaps to mirror enhanced + flexibility in the csdisposing and csdisposing_derived (C#) typemaps. If provided + the contents are generated as the delete/dispose method's parameters declaration. + +2019-03-30: wsfulton + [C#] #421 Fix FxCop warning CA1063 by implementing the recommended Dispose methods for + the IDisposable interface. Previously just the Dispose() method was generated. + Now the Dispose() and Dispose(bool disposing) methods are generated. + Changes are required if custom "csfinalize", "csdestruct" or "csdestruct_derived" + typemaps are being used. Details in #421 on Github. SWIG will error out if one of + the "csfinalize, "csdestruct" or "csdestruct_derived" typemaps are found. Example + error message: + + foo.h:60: Error: A deprecated csfinalize typemap was found for Foo, please remove + it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the + csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps. + + *** POTENTIAL INCOMPATIBILITY *** + +2019-03-25: Liryna + [C#] #1143 Add std_list.i for std::list support. + The C# std::list wrappers are made to look and feel like a C# + System.Collections.Generic.LinkedList<> collection. + The IEnumerable<> interface is implemented in the proxy class. + The ICollection<> interface can also be implemented to provide enhanced functionality + whenever a C++ operator== is available. This is the case for when T is a + primitive type or a pointer. If T does define an operator==, then use the + SWIG_STD_LIST_ENHANCED macro to obtain this enhanced functionality, for example: + + SWIG_STD_LIST_ENHANCED(SomeNamespace::Klass) + %template(ListKlass) std::list; + +2019-03-18: richardbeare + [R] #1328 Non-trivial enums are working now. The enum values are now obtained from + the C/C++ layer. const reference enums and C++11 enum classes are also now working. + +2019-03-14: mochizk + [Javascript] #1500 Fix compilation errors due to deprecating V8 API in Node.js. + New V8 API is used if node.js >= v10.12, or if V8 >= v7.0. + +2019-03-12: vadz + [C#] #1495 Add std_set.i for std::set support. + +2019-03-11: dirteat,opoplawski + [Octave] Fix compilation errors in Octave 5.1. + + error: format not a string literal and no format arguments [-Werror=format-security] + +2019-02-28: wsfulton + [Java] std::vector improvements for types that do not have a default constructor. + + The std::vector wrappers have been changed to work by default for elements that are + not default insertable, i.e. have no default constructor. This has been achieved by + not wrapping: + + vector(size_type n); + + Previously the above had to be ignored via %ignore. + + If the above constructor is still required it can be added back in again via %extend: + + %extend std::vector { + vector(size_type count) { return new std::vector< T >(count); } + } + + Alternatively, the following wrapped constructor could be used as it provides near-enough + equivalent functionality: + + vector(jint count, const value_type& value); + + *** POTENTIAL INCOMPATIBILITY *** + +2019-02-25: wsfulton + [Python] Fix compile errors wrapping overloaded functions/constructors where a vararg + function is declared after a non-vararg function. + +2019-02-23: zphensley42 + Use fully qualified name 'java.lang.Object' instead of 'Object' in generated code to + avoid clashes with wrapped C++ classes called 'Object'. + +2019-02-23: gtbX + [Java] #1035 Add (const char *STRING, size_t LENGTH) typemaps in addition to the non-const + typemaps (char *STRING, size_t LENGTH) which does not attempt to write back to the const + string. + +2019-02-22: tamuratak + [Ruby] #984 Add support for RTypedData introduced in Ruby 1.9.3. + +2019-02-22: ZackerySpytz + #1483 Fix compilation failures when a director class has final methods. + +2019-02-21: wsfulton + [Java] #1240 Suppress Java 9 deprecation warnings on finalize method. + +2019-02-21: ZackerySpytz + #1480 Fix some rejections of valid floating-point literals. + +2019-02-19: wsfulton + #1475 Fix regression parsing gcc preprocessor linemarkers in the form: + + # linenum filename flags + +2019-02-18: jakecobb + [Python] #945 #1234 Elements in std::vector memory access fix. + + Accessing an element in a std::vector obtains a reference to the element via an + iterator pointing to the element in the container. If the vector is garbage collected, + the SWIG wrapper containing the pointer to the element becomes invalid. The fix is + to obtain a back-reference to the container by the wrapper to the element in the Python + layer to prevent the garbage collector from destroying the underlying container. + +2019-02-17: wsfulton + Fix typemap matching to expand template parameters when the name contains + template parameters. In the %typemap below the type is T and the name is X::make + and the name now expands correctly to X< int >::make + + template struct X { + %typemap(out) T X::make "..." + T make(); + }; + + %template(Xint) X; + +2019-02-16: wsfulton + Fix parser error containing multiple #define statements inside an enum. + + The second #define fails to parse: + + enum FooEnum { + ENUM1 = 0, + ENUM2 = 1, + + #define MACRO_DEF1 "Hello" + #define MACRO_DEF2 "World!" + + ENUM3 = 2, + ENUM4 = 3, + }; + + Bug mentioned at https://sourceforge.net/p/swig/patches/333/ + +2019-02-14: wsfulton + Add some missing copy constructors into STL containers. + +2019-02-14: bkotzz + [Java] #1356 Add STL containers: + std::unordered_map + std::unordered_set + std::set + +2019-02-14: bkotzz + [Java] #1356 std::map wrappers have been modified. Now the Java proxy class + extends java.util.AbstractMap. The std::map container looks and feels much like + a java.util.HashMap from Java. + + A few members have changed their names. If the old method signatures are needed, + then copy std_map.i from swig-3.0.12 and use that instead. Alternatively, + add the old missing methods to the new methods by using the following %proxycode: + + %extend std::map { + %proxycode %{ + // Old API + public boolean empty() { + return isEmpty(); + } + public void set($typemap(jboxtype, K) key, $typemap(jboxtype, T) x) { + put(key, x); + } + public void del($typemap(jboxtype, K) key) { + remove(key); + } + public boolean has_key($typemap(jboxtype, K) key) { + return containsKey(key); + } + %} + } + + *** POTENTIAL INCOMPATIBILITY *** + +2019-02-13: ZackerySpytz + #1469 Add support for C++17 hexadecimal floating literals. + +2019-02-11: wsfulton + [OCaml] #1437 OCaml has been give the 'Experimental' language status. The examples work + and most of the test-suite is also working, so it is quite close to being a 'Supported' language. + +2019-02-10: ZackerySpytz + #1464 Add support for C++14 binary integer literals. + +2019-02-10: ZackerySpytz + #1450 Add support for C++11 UCS-2 and UCS-4 character literals. Also, add support for + C++17 UTF-8 character literals. + +2019-02-10: wsfulton + [MzScheme] #1437 MzScheme/Racket is now an 'Experimental' language. The examples work + and a large portion of the test-suite is also working. + +2019-02-10: wsfulton + [MzScheme] Destructor wrappers were not being generated. + +2019-02-10: wsfulton + [MzScheme] Static variable wrappers fixed - $argnum was not expanded. + +2019-02-10: sethrj + #1452 Fix %apply for anonymous template instantiations + +2019-02-09: olly + [PHP] Fix access to already released memory during PHP module + shutdown, which often didn't cause visible problems, but could + result in segmentation faults, bus errors, etc. Fixes #1170, + reported by Jitka Plesníková. + +2019-02-09: olly + [PHP] A renamed constructor is now wrapped as a static method in + PHP. + +2019-02-08: olly + [PHP] Don't generate code which references $r when $r hasn't been + defined. This could happen in overloaded methods which returned + void and took at least one const std::string& parameter. + +2019-02-08: olly + [PHP] The generated code is now compatible with PHP 7.3, and the + testsuite now runs cleanly with this version too. + +2019-02-05: wsfulton + #1437 SWIG now classifies the status of target languages into either 'Experimental' or + 'Supported'. This status is provided to indicate the level of maturity to expect when using + a particular target language as not all target languages are fully developed. Details are + in the Introduction.html chapter of the documentation. + +2019-02-04: wsfulton + [CFFI] #1447 Common Lisp CFFI has been disabled as a target language in SWIG as part of a + clean up to remove target languages that have been neglected/not functional. + +2019-02-04: wsfulton + [Allegrocl] #1447 Allegro Common Lisp has been disabled as a target language in SWIG as part of a + clean up to remove target languages that have been neglected/not functional. + +2019-02-04: wsfulton + [Chicken] #1447 CHICKEN has been disabled as a target language in SWIG as part of a + clean up to remove target languages that have been neglected/not functional. + +2019-02-04: wsfulton + [CLISP] #1447 GNU Common Lisp has been disabled as a target language in SWIG as part of a + clean up to remove target languages that have been neglected/not functional. + +2019-02-04: wsfulton + [S-EXP] #1447 Common Lisp S-Exp has been disabled as a target language in SWIG as part of a + clean up to remove target languages that have been neglected/not functional. + +2019-02-04: wsfulton + [UFFI] #1447 Common Lisp UFFI has been disabled as a target language in SWIG as part of a + clean up to remove target languages that have been neglected/not functional. + +2019-02-04: wsfulton + [Pike] #1447 Pike has been disabled as a target language in SWIG as part of a + clean up to remove target languages that have been neglected/not functional. + +2019-02-04: wsfulton + [Modula3] #1447 Modula3 has been disabled as a target language in SWIG as part of a + clean up to remove target languages that have been neglected/not functional. + +2019-02-02: ahnolds + [Python] Documentation enhancements for Python: + + #728 Fixed the handling of autodoc when using -fastproxy. + + #1367 Added documentation to wrapped member variables using the + property(... doc="...") construct. + + Only show a single documentation entry for functions with default arguments when + using autodoc. + + Fixed a bug where a cached doxygen docstring could be deleted while still in use, + causing swig to segfault. + +2019-01-31: olly + SWIG now requires a target language to be specified instead of + defaulting to wrapping for Tcl. Specifying swig --help without + a target language now just shows the generic help. The -nolang + option has been removed. + +2019-01-28: ZackerySpytz + [OCaml] #1429 Remove support for OCaml versions < 3.12.0. + + *** POTENTIAL INCOMPATIBILITY *** + +2019-01-22: vadz + [Ruby, Octave] #1424 Improve autodoc parameter naming. + +2019-01-22: vadz + [Python] #1271 #1423 Always include default parameter values in autodoc strings. + +2019-01-19: vadz + #1272, #1421 When a function's parameter is a keyword, the name of the paramater is + no longer simply changed to argN, where N is the argument number. Instead the + parameter name is changed to the renaming rules for keywords that normally apply to + symbols such as classes/functions etc. Note that unlike other symbol renaming, + parameter renaming does not issue a warning when the parameter is renamed. This + change only affects languages where the parameter names are actually used, for example, + Java function parameter lists in the proxy class or Python documentation comments. + +2019-01-18: wsfulton + #1420 Fix gdb debugger functions 'swigprint' and 'locswigprint' from swig.gdb to + work with newer versions of gdb-8. Fixes errors when debugging SWIG source with gdb: + + (gdb) swigprint n + Undefined command: "Printf". Try "help". + +2019-01-16: wsfulton + Python static method wrapper changes + + - Static method wrappers were using the 'fastproxy' approach by default. + This is inconsistent with instance method wrappers. The fastproxy approach + is now turned off by default to be consistent with instance methods. + Static method wrappers can now also be controlled using the -fastproxy and + -olddefs options. + + Example: + + struct Klass { + static int statmethod(int a = 2); + }; + + generates by default: + + class Klass(object): + ... + @staticmethod + def statmethod(a=2): + return _example.Klass_statmethod(a) + + instead of the following (which can be restored by using -fastproxy): + + class Klass(object): + ... + statmethod = staticmethod(_example.Klass_statmethod) + + - Modernise wrappers for static methods to use decorator syntax - @staticmethod. + + - Add missing runtime test for static class methods and using the actual class method. + +2019-01-12: ZackerySpytz + [OCaml] #1403 #1194 Fix compilation problems for OCaml >= 4.03.0 due to OCaml using + int64_t instead of int64. + +2019-01-11: ZackerySpytz + [OCaml] #1400 Fix the getters and setters of non-static member variables. + +2019-01-07: wsfulton + #358 Add VOID to windows.i + +2019-01-05: wsfulton + #948 #1019 #1273 Fix for C++11 raw strings where the delimiters were mistakenly left + in the string contents in situations where the string was copied into generated code. + For example, %constant, the "docstring" feature and for C#/Java/D constants turned on + with %javaconst/%csconst/%dmanifestconst. + +2019-01-05: wsfulton + [Ruby] #538. Fix Ruby support for %feature("docstring"). + +2019-01-03: wsfulton + #1202 Fix overloading of non-pointer class types in scripting languages when overloaded + with a pointer and a NULL scripting language equivalent is used, eg None in Python. + + The implementation changes the SWIGTYPE, SWIGTYPE& and SWIGTYPE&& typecheck typemaps to + prevent accepting a conversion to a NULL pointer. + +2019-01-03: ZackerySpytz + [OCaml] #1386 Fix the OCaml examples and test suite for out-of-source builds. + +2019-01-01: wsfulton + [Python] #639 remove duplicate proxy method definitions for global function wrappers. + + Global functions previously generated two definitions, eg: + + def foo(): + return _example.foo() + foo = _example.foo + + The first definition is replaced by the second definition and so the second definition + is the one used when the method is actually called. Now just the first definition is + generated by default and if the -fastproxy command line option is used, just the second + definition is generated. The second definition is faster as it avoids the proxy Python + method as it calls the low-level C wrapper directly. Using both -fastproxy and -olddefs + command line options will restore the previously generated code as it will generate both + method definitions. + + With this change, the wrappers for global C/C++ functions and C++ class methods now work + in the same way wrt to generating just a proxy method by default and control via + -fastproxy/-olddefs options. + +2018-12-20: hasinoff,wsfulton + [Java] #1334 Set Java thread name to native thread name when using directors. + + Default is to use name "Thread-XXX" and is still works like this by default. However, + adding the following will turn on the thread name setting (works for more recent + versions of Linux and MacOS): + + %begin %{ + #define SWIG_JAVA_USE_THREAD_NAME + %} + +2018-12-20: chlandsi + [Python] #1357. Fix overriding __new__ in Python 3.6. + + Fixes SystemError: Objects/tupleobject.c:81: bad argument to internal function" + +2018-12-16: wsfulton + [Python] #848 #1343 The module import logic has changed to stop obfuscating real ImportError + problems. Only one import of the low-level C/C++ module from the pure Python module is + attempted now. Previously a second import of the low-level C/C++ module was attempted + after an ImportError occurred and was done to support 'split modules'. A 'split module' is + a configuration where the pure Python module is a module within a Python package and the + low-level C/C++ module is a global Python module. Now a 'split module' configuration is + no longer supported by default. This configuration can be supported with a simple + customization, such as: + + %module(package="mypackage", moduleimport="import $module") foo + + or if using -builtin: + + %module(package="mypackage", moduleimport="from $module import *") foo + + instead of + + %module(package="mypackage") foo + + See the updated Python chapter titled "Location of modules" in the documentation. + +2018-12-11: tlby + [Perl] #1374 repair EXTEND() handling in typemaps + +2018-12-06: vadz + #1359 #1364 Add missing nested class destructor wrapper when the nested class is + inside a template. Removes associated bogus 'Illegal destructor name' warning. Only + occurred when the nested class' destructor is explicitly specified. + +2018-12-04: adr26 + [Python] #1368 #1369 Access Violation in tp_print caused by mismatched Python/extension + CRT usage + + Remove all use of tp_print, as this API uses a FILE*, which can be + mismatched when modules are built with different C libraries from + the main python executable. + + This change also brings consistent output between Python 2 and 3 for the 'cvar' SWIG + object (that contains the global variables) and SWIG packed objects (such as callback + constants). + +2018-12-04: wsfulton + [Python] #1282 Fix running 'python -m' when using 'swig -builtin' + + Similar to the earlier PEP 366 conforming fix for non-builtin. + +2018-11-29: adr26 + [Python] #1360 Leak of SWIG var link object + + Fix reference counting on _SWIG_globals to allow var link to be freed on module unload. + +2018-11-28: wsfulton + [Python] When using -builtin, the two step C-extension module import is now + one step and the wrapped API is only available once and not in an underlying + module attribute like it is without -builtin. To understand this, consider a + module named 'example' (using: %module example). The C-extension is compiled into + a Python module called '_example' and a pure Python module provides the actual + API from the module called 'example'. It was previously possible to additionally + access the API from the module attribute 'example._example'. The latter was an + implementation detail and is no longer available. It shouldn't have been used, but + if necessary it can be resurrected using the moduleimport attribute described in the + Python chapter of the documentation. If both modules are provided in a Python + package, try: + + %module(moduleimport="from . import _example\nfrom ._example import *") example + or more generically: + %module(moduleimport="from . import $module\nfrom .$module import *") example + + and if both are provided as global modules, try: + + %module(moduleimport="import _example\nfrom _example import *") example + or more generically: + %module(moduleimport="import $module\nfrom $module import *") example + + The module import code shown will appear in the example.py file. + +2018-11-24: vadz + #1358 Fix handling of abstract base classes nested inside templates + + Correct detecting of whether a derived class method overrides a pure virtual + base class method when both classes are nested inside a template class: this + notably didn't work correctly for methods taking parameters of the base class + type. + +2018-11-22: rupertnash + [Python] #1282 Make generated module runnable via python -m (PEP 366 conforming) + + Previously any SWIG generated modules in a package would fail with an ImportError + when using 'python -m' for example 'python -m mypkg.mymodule'. + + This fix also allows the SWIG generated module to be placed into a directory and + then renamed __init__.py to convert the module into a package again. This ability + stopped working in swig-3.0.9. However, only Python 2.7 or 3.3 and later work. If + Python 3.2 support is needed, use moduleimport in %module to customise the import + code. + +2018-11-13: wsfulton + #1340 Remove -cppcast and -nocppcast command line options (this was an option + available to the scripting language targets). + + The -cppcast option is still turned on by default. The -nocppcast option + to turn off the use of c++ casts (const_cast, static_cast etc) has been + removed. However, defining SWIG_NO_CPLUSPLUS_CAST will still generate C casts + instead of C++ casts for C++ wrappers. + + *** POTENTIAL INCOMPATIBILITY *** + +2018-11-13: wsfulton + [Python] #1340 Remove -outputtuple and -nooutputtuple command line options. + + Both the command line and %module options of the same name have been + removed. These were undocumented. The -outputtuple option returned a + Python tuple instead of a list, mostly typically in the OUTPUT + typemap implementations. + + It unclear why a tuple instead of a list return type is needed and + hence this option has been removed as part of the simplification of + the SWIG Python command line options for SWIG 4. + +2018-11-13: wsfulton + [Python] #1340 Remove -noproxyimport command line option. + + This option turned off the insertion of Python import statements + derived from a %import directive. For example given: + + %module module_b + %import "module_a.i" + + then module_b.py will contain: + + import module_a + + *** POTENTIAL INCOMPATIBILITY *** + +2018-10-29: AlexanderGabriel + [PHP] The following PHP7 reserved keywords are now only renamed by + SWIG when used as function names in the API being wrapper: + __halt_compiler array die echo empty eval exit include include_once + isset list print require require_once return unset + +2018-10-22: olly,wsfulton + [Python] #1261 #1340 Turn on many optimisation options by default and rationalise the + number of command line options. + + There were an unnecessary number of command line options and many of these have now + been removed in a drive for simplification. Some were needed to support older versions + of Python (2.6 and earlier). + + Many of the options could be turned on individually and when using -O. Previously -O + resulted in turning on a set of options: + + -modern -fastdispatch -nosafecstrings -fvirtual -noproxydel + -fastproxy -fastinit -fastunpack -fastquery -modernargs -nobuildnone + + Now -O results in turning on this reduced set: + + -fastdispatch -fastproxy -fvirtual + + The following options are now on by default, a deprecated warning is displayed if they + are used: + -fastinit Class initialisation code done in C/C++ rather than in Python code. + -fastquery Python dictionary used for lookup of types. + -fastunpack Faster unpacking of function arguments in C/C++ wrappers. + -modern Use Python 2.3 features such as object and property. + -modernargs Use Python 2.3 C APIs for unpacking arguments in tuples. + -noproxydel Stop generating a proxy __del__ method for backwards compatiblity. + -safecstrings No discernable difference + + The following options have been removed altogether: + -aliasobj0 + -buildnone + -classptr + -new_repr + -newrepr + -noaliasobj0 + -nobuildnone + -nocastmode + -nodirvtable + -noextranative + -nofastinit + -nofastproxy + -nofastquery + -nomodern + -nomodernargs + -nooutputtuple + -nosafecstrings + -old_repr + -oldrepr + -proxydel + + -new_vwm is no longer supported. Use the -newvwm alias instead. + + *** POTENTIAL INCOMPATIBILITY *** + +2018-10-22: olly + [Python] #1261 Remove command line option no longer needed as Python 2.3 and earlier + are no longer supported: + + -classic + +2018-10-09: wsfulton + [D, Go, Guile, Lua, Mzscheme, Ocaml, Perl5, Php, Scilab, Tcl] + Allow wrapping of std::map using non-default comparison function. + +2018-10-09: vadz + [Java] #1274 Allow wrapping of std::map using non-default comparison function. + +2018-10-04: wsfulton + [Python] #1126 Fix C default arguments with -builtin and -fastunpack and -modernargs. + Problem occurred when there is just one (defaulted) parameter in the parameter list. + +2018-09-24: wsfulton + [Python] #1319 C++11 hash tables implementation is finished now (including for -builtin): + std::unordered_map + std::unordered_set + std::unordered_multimap + std::unordered_multiset + +2018-09-21: wsfulton + [Python] Fix when using -builtin and wrapping std::map, std::set, std::unordered_map or + std::unordered_set to ensure __contains__ is called. This is a wrapper for the STL + container's find method. Without it, Python will do its own slower sequence search. + +2018-09-19: wsfulton + [Python] Fix functors (wrapped as __call__) when using -builtin -modern -fastunpack. + +2018-09-02: andreas.gaeer,tkrasnukha + [Python] #1321 Fix assert in PyTuple_GET_SIZE in debug interpreter builds of python-3.7 + when calling tp_new. + +2018-09-01: ChristopherHogan + [Guile] #1288 Fix garbage collection for guile >= 2.0.12. + +2018-08-31: wsfulton + [Python] #1319 C++11 hash tables support: + std::unordered_map + std::unordered_set + std::unordered_multimap + std::unordered_multiset + is now compiling and working (sorting using -builtin not fully functional yet though). + +2018-08-20: wkalinin + #1305 Fix nested structure symbol tables in C mode to fix member name conflicts + in different structs with the same nested struct member name. + +2018-08-18: wsfulton + [Python] #688 Fix makefile recursion when running python test-suite. + +2018-08-18: wsfulton + [Python] #1310 Re-implement Python -fastproxy option. + + The previous implementation failed with Python 3 and abstract base clases. + The new implementation replaces the Python 2 implementation using + new.instancemethod with the C API PyMethod_New to match the equivalent Python 3 + implementation which uses PyInstanceMethod_New. + + The new approach runs slightly faster. See #1310. + +2018-08-12: gmazzamuto + [Python] #1283 Update pybuffer.i library to use new-style Python buffer C API. + +2018-08-12: brianhatwood,wsfulton + [Java] #1303 #1304 Fix crash in directors when using OUTPUT and INOUT typemaps in typemaps.i and + passing NULL pointers in C++ to director method overloaded and implemented in Java. + +2018-08-10: wsfulton + [Python] #1293 Improve TypeError message inconsistencies between default and fastdispatch + mode when handling overloaded C++ functions. Previously the error message did not always + display the possible C/C++ prototypes in fastdispatch mode. + +2018-08-02: furylynx,jacobwgillespie,p2k + [Javascript] #1290, #968. Add support for NodeJS versions 2-10. + +2018-07-31: wsfulton + [Python] #1293 Overloaded C++ function wrappers now raise a TypeError instead + of NotImplementedError when the types passed are incorrect. This change means + there is now consistency with non-overloaded function wrappers which have always + raised TypeError when the incorrect types are passed. The error message remains + the same and is for example now: + + TypeError: Wrong number or type of arguments for overloaded function 'f'. + Possible C/C++ prototypes are: + f(int) + f(char const *) + + instead of: + + NotImplementedError: Wrong number or type of arguments for overloaded function 'f'. + Possible C/C++ prototypes are: + f(int) + f(char const *) + + *** POTENTIAL INCOMPATIBILITY *** + +2018-06-23: wsfulton + [Python] #718 Fix pythonnondynamic feature for modern classes + + Fixes nondynamic mode when an instance variable is set with the same + name as a class variable in a class derived from a SWIG proxy class. + This corner case set an instance variable instead of raising an AttributeError. + + Also fix %pythonnondynamic in Python 3 with -modern. The metaclass + containing the implementation was previously not being applied in Python 3. + +2018-07-17: petrmitrichev,wsfulton + [Python] #1275 #1279 Initialize function-local statics (singletons) that call Python + code during Python module initialization in order to avoid deadlocks with subsequent + multi-threaded usage. + +2018-06-15: wsfulton + [Python] Fix seg fault using Python 2 when passing a Python string, containing + invalid utf-8 content, to a wstring or wchar * parameter. A TypeError is thrown instead, eg: + + %include + void instring(const std::wstring& s); + + instring(b"h\xe9llooo") # Python + +2018-06-15: wsfulton + [Python] Python 3.7 support: Replace use of deprecated PyUnicode_GetSize with + PyUnicode_GetLength to remove deprecated warnings compiling the C/C++ wrappers. + +2018-06-12: wsfulton + [Python] Python 3.7 support: The %pythonabc feature in pyabc.i now uses base classes + collections.abc.MutableSequence + collections.abc.MutableMapping + collections.abc.MutableSet + instead of + collections.MutableSequence + collections.MutableMapping + collections.MutableSet + as the latter are deprecated in Python 3.7 and are due to be removed in Python 3.8. + The classes in collections.abc.* are available from Python 3.3 onwards. If you + require support for Python 3.2, then copy the pyabc.i file and modify by removing + the few instances of the .abc sub-module. + + *** POTENTIAL INCOMPATIBILITY *** + +2018-06-12: olly,wsfulton + [Python] #701 Remove support for Python versions < 2.7 and 3.0 and 3.1. + + *** POTENTIAL INCOMPATIBILITY *** + +2018-06-11: olly + [Python] Fix new GCC8 warnings in generated code by avoiding casts + between incompatible function types where possible, and by + suppressing the warning when it's due to the design of Python's C + API. Fixes #1259. + +2018-06-08: philippkraft + [Python] Stop exposing _swigregister to Python. It's not + useful for user Python code to call this, and it just clutters the + API unnecessarily. Fixes #1225. + +2018-06-07: cmfoil, kabbi, Jamie Kirkpatrick, markok314, vadz, wsfulton, Yann Diorcet + #170 Doxygen documentation support added. This allows translation of Doxygen comments + into JavaDoc and PyDoc documentation. It is enabled via the -doxygen command line + option. See the Doxygen.html chapter in the documentation for further information. + +2018-06-07: olly + [PHP] We've finally removed support for %pragma(php4) which was + deprecated back in 2008. Use %pragma(php) instead, which has been + supported since at least 2005. + + *** POTENTIAL INCOMPATIBILITY *** + +2018-06-07: olly + [PHP5] Support for PHP5 has been removed. PHP5 is no longer + actively supported by the PHP developers and security support for + it ends completely at the end of 2018, so it doesn't make sense + to include support for it in the upcoming SWIG 4.0.0 release. + + *** POTENTIAL INCOMPATIBILITY *** + +2018-06-06: olly + [Lua] Improve configure probes for Lua headers and libs used in testsuite. + +2018-05-15: kwwette + [Octave] add support for version 4.4 + - Should not introduce any user-visible incompatibilities + +2018-05-15: wsfulton + [C#, D, Java] Fix lookup of csconstruct, dconstruct and javaconstruct typemaps. + The C++ namespace was previously ignored when looking up the typemap. + +2018-05-15: wsfulton + [Javascript] Fix generated C++ code when using %nspace on namespaces that are more + than two levels deep. + +2018-05-14: wsfulton + Issue #1251 Add support for C++17 nested namespace definitions, + for example: + namespace A::B { ... } + +2018-05-11: wsfulton + [C#, D, Java] Add support so that the %csmethodmodifiers, %dmethodmodifiers, + %javamethodmodifiers can modify the method modifiers for the destructor wrappers + in the proxy class: dispose, Dispose, delete. With this feature, it is now possible + to make a C# proxy class sealed, eg when wrapping a class X, the virtual method modifiers + can be removed using: + + %typemap(csclassmodifiers) X "public sealed class" + %csmethodmodifiers X::~X "public /*virtual*/"; + +2018-04-18: olly + [Python] Suppress new pycodestyle warning: + E252 missing whitespace around parameter equals + +2018-04-07: goatshriek + [Ruby] #1213 Fix ruby %alias directive for global C/C++ functions. + +2018-04-03: olly + [Ruby] Fix to pass Qnil instead of NULL to rb_funcall(), which silences GCC + -Wconversion-null warning (on by default with recent GCC). + +2018-03-09: wsfulton + [Java] #1184 Fix swigReleaseOwnership() and swigTakeOwnership() regression + for non-director classes. Restores a dynamic_cast which was previously removed. + +2018-03-07: llongi + Github PR #1166 - Fix preprocessor handling of macros with commas + in a // comment. + +2018-02-18: JPEWdev + Patch #1164 - Add support for a command-line options file, also sometimes + called a response file. This is useful if the command-line options exceed + the system command-line length limit. To use, put the command-line options + into a file, then provide the file name prefixed with @, for example using + a file called args.txt: + + swig @args.txt + +2018-02-11: wsfulton + [Javascript] #1187 Fix compilation error wrapping std::complex via + std_complex.i. + +2018-01-30: smarchetto + [Scilab] add type name argument in SWIG_ptr() function to cast from pointer address to typed pointers + +2018-01-16: wsfulton + Expressions following a preprocessor directive must now be separated by whitespace + or non-numeric characters. This syntax change makes the SWIG preprocessor work like + the C preprocessor in this area. + + For example, the following code used be accepted as valid syntax: + #if1 + #define ABC 123 + #endif + + Now you get an error: + example.h:1: Error: Unknown SWIG preprocessor directive: if1 (if this is a block of + target language code, delimit it with %{ and %}) + example.h:3: Error: Extraneous #endif. + + The following is the correct syntax: + #if 1 + #define ABC 123 + #endif + + The following of course also works: + #if(1) + #define ABC 123 + #endif + + *** POTENTIAL INCOMPATIBILITY *** + +2018-01-15: wsfulton + Fix issue #1183. Floating point exception evaluating preprocessor expressions + resulting in division by zero. + +2018-01-14: wsfulton + Fix issue #1172. Seg fault parsing invalid exponents in the preprocessor. + +2018-01-12: Liryna + [C#] Patch #1128. Add ToArray function to std::vector wrappers. + +2018-01-12: wsfulton + [Java] Fix issue #1156. Add missing throws clause for interfaces when using the + %interface family of macros. + +2018-01-05: wsfulton + Fix default arguments using expressions containing -> syntax error. Problem reported on + swig-user mailing list. + +2017-12-30: wsfulton + [Python] Replace pep8 with pycodestyle for checking the Python code style when + running Python tests. + +2017-12-30: davedissian + Fixed a symbol lookup issue when encountering a typedef of a symbol from the tag + namespace to the global namespace when the names are identical, such as 'typedef + struct Foo Foo;'. + +2017-12-13: wsfulton + [Perl] add missing support for directorfree typemaps. + +2017-12-13: wsfulton + Issue #1167 Fix directorout typemaps which were causing undefined behaviour when + returning pointers by reference. + +2017-12-08: olly + [PHP] Use ZEND_MODULE_GLOBALS_ACCESSOR to access globals so the + generated code builds when PHP was built with ZTS enabled. + +2017-12-04: wsfulton + [Python] Add missing checks for failures in calls to PyUnicode_AsUTF8String. Previously a + seg fault could occur when passing invalid UTF8 strings (low surrogates), eg passing + u"\udcff" to the C layer (Python 3). + +2017-11-24: joequant + [R] Fix #1124 and return R_NilValue for null pointers + +2017-11-29: wsfulton + [Java] director exception handling improvements. + + When a director method throws an exception and it is caught by DirectorException + and passed back to Java using Swig::DirectorException::throwException, the Java + stack trace now contains the original source line that threw the exception. + + Deprecate Swig::DirectorException::raiseJavaException, please replace usage with + Swig::DirectorException::throwException. + + *** POTENTIAL INCOMPATIBILITY *** + +2017-10-26: wsfulton + Add support for C++11 ref-qualifiers when using directors. + +2017-10-26: wsfulton + Fix generated code when using directors and methods returning const ref pointers. + +2017-10-26: wsfulton + [C#, D, Java, Octave, R, Scilab] Port director typemaps to these additional languages. + Issue #700. + +2017-10-26: radarsat1 + [Ruby Python] Patch #1029 - Correct handling of null using directors and shared_ptr. + +2017-10-10: joequant + [R] pass enum expressions to R. This will generate + incorrect files when there is an arithmetic expression + in the enum, but this is better than silently generating + incorrect code + +2017-10-09: olly + [PHP] Fix incorrect wrapper code generated when there's a + combination of overloading, parameters with a default value + and %newobject. Fixes https://sourceforge.net/p/swig/bugs/1350/ + +2017-10-09: olly + Remove GCJ support. It isn't in a good state and doesn't seem to + be used, and GCC7 dropped GCJ. Closes + https://sourceforge.net/p/swig/bugs/823/ + +2017-10-07: olly + Fix preprocessor handling of empty macro arguments to match that of + C/C++ compilers. Fixes issue #1111 and + https://sourceforge.net/p/swig/bugs/826/ + +2017-10-06: wsfulton + [Python] Issue #1108. Fix platform inconsistency in Python default argument handling. + 32 bit and 64 bit compiled versions of SWIG generated different Python files + when default arguments were outside the range of 32 bit signed integers. + The default arguments specified in Python are now only those that are in the + range of a 32 bit signed integer, otherwise the default is obtained from C/C++ code. + +2017-10-02: wsfulton + [C#] Fix std::complex types passed by value. + +2017-10-02: wsfulton + [Javascript, Python, Ruby] Issue #732 - Missing type information for std::complex + in std_complex.i meant that previously std::complex always had to be fully qualified + in order to be wrapped with the appropriate typemaps. + +2017-10-01: joequant + allow R package names with docs + allowing multiple get accessors in R + fix smart-pointer and NAMESPACE support + constructors now returning smart pointers (if class + declared as such) + smart-pointer classes deriving from parent smart-pointers + +2017-09-29: wsfulton + Issue #1100 - Allow an instantiated template to have the same name in the target + language as the C++ template name, for example, this is now possible: + + template struct X { ... }; + %template(X) X; + +2017-09-23: wsfulton + Issue #1098. Fix overloading of shared_ptr with underlying pointer types, eg: + + void m(std::shared_ptr p); + void m(T &p); + void m(T *p); + + Only the first method is wrapped and the others are ignored/shadowed. + The implementation is done via a new attribute in the 'typecheck' typemap called + 'equivalent'. If specified, it must contain the equivalent pointer type for overloading + and can only be used for the special SWIG_TYPECHECK_POINTER precedence level. + The shared_ptr 'typecheck' typemaps have been modified accordingly. + Here is a simplified version: + + %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="T *") + T, + T CONST &, + T CONST *, + T *CONST&, + std::shared_ptr< T >, + std::shared_ptr< T > &, + std::shared_ptr< T > *, + std::shared_ptr< T > *& + { ... } + + Overloading with any of these types will result in SWIG ignoring all but the first + overloaded method by default. Without the 'equivalent' attribute, wrapping the overloaded + methods resulted in types being shadowed (scripting languages) or code that did not + compile (statically typed languages). + +2017-09-19: futatuki + [Python] #1003 Add --with-2to3=/path/to/2to3 option to configure. + +2017-09-18: wsfulton + Fix type promotion wrapping constant expressions of the form: + # define EXPR_MIXED1 (0x80 + 11.1) - 1 + This was previously an integral type instead of a floating point type. + +2017-09-17: wsfulton + Fix generated code for constant expressions containing wchar_t L literals such as: + # define __WCHAR_MAX (0x7fffffff + L'\0') + # define __WCHAR_MIN (-__WCHAR_MAX - 1) + +2017-09-10: mlamarre + [Python] Patch #1083. Define_DEBUG to 1 to do exactly like Visual Studio + /LDd, /MDd or /MTd compiler options. + +2017-08-25: wsfulton + Issue #1059. Add support for C++11 ref-qualifiers on non-static member functions. + Members with lvalue ref-qualifiers such as: + + struct RQ { + void m1(int x) &; + void m2(int x) const &; + }; + + are wrapped like any other member function. Member functions with rvalue ref-qualifiers + are ignored by default, such as: + + struct RQ { + void m3(int x) &&; + void m4(int x) const &&; + }; + + example.i:7: Warning 405: Method with rvalue ref-qualifier m3(int) && ignored. + example.i:8: Warning 405: Method with rvalue ref-qualifier m4(int) const && ignored. + + These can be unignored and exposed to the target language, see further documentation in + CPlusPlus11.html. + +2017-08-16: wsfulton + Fix #1063. Add using declarations to templates into typedef table. + + Using declarations to templates were missing in SWIG's internal typedef tables. + This led to a few problems, such as, templates that did not instantiate and generated + C++ code that did not compile as SWIG did not know what scope the template was + in. This happened mostly when a using declaration was used on a template type in a + completely unrelated namespace. + +2017-08-16: wsfulton + Fix type lookup in the presence of using directives and using declarations. + + Fix some cases of type lookup failure via a combination of both using directives and + using declarations resulting in C++ code that did not compile as the generated type was + not fully qualified for use in the global namespace. Example below: + + namespace Space5 { + namespace SubSpace5 { + namespace SubSubSpace5 { + struct F {}; + } + } + using namespace SubSpace5; + using SubSubSpace5::F; + void func(SubSubSpace5::F f); + } + +2017-08-16: wsfulton + Issue #1051. %template scope enforcement and class definition fixes. + + The scoping rules around %template have been specified and enforced. + The %template directive for a class template is the equivalent to an + explicit instantiation of a C++ class template. The scope for a valid + %template instantiation is now the same as the scope required for a + valid explicit instantiation of a C++ template. A definition of the + template for the explicit instantiation must be in scope where the + instantiation is declared and must not be enclosed within a different + namespace. + + For example, a few %template and C++ explicit instantiations of std::vector + are shown below: + + // valid + namespace std { + %template(vin) vector; + template class vector; + } + + // valid + using namespace std; + %template(vin) vector; + template class vector; + + // valid + using std::vector; + %template(vin) vector; + template class vector; + + // ill-formed + namespace unrelated { + using std::vector; + %template(vin) vector; + template class vector; + } + + // ill-formed + namespace unrelated { + using namespace std; + %template(vin) vector; + template class vector; + } + + // ill-formed + namespace unrelated { + namespace std { + %template(vin) vector; + template class vector; + } + } + + // ill-formed + namespace unrelated { + %template(vin) std::vector; + template class std::vector; + } + + When the scope is incorrect, an error now occurs such as: + + cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and + was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'. + + Previously SWIG accepted the ill-formed examples above but this led to + numerous subtle template scope problems especially in the presence of + using declarations and using directives as well as with %feature and %typemap. + + Actually, a valid instantiation is one which conforms to the C++03 + standard as C++11 made a change to disallow using declarations and + using directives to find a template. + + // valid C++03, ill-formed C++11 + using std::vector; + template class vector; + + Similar fixes for defining classes using forward class references have + also been put in place. For example: + + namespace Space1 { + struct A; + } + namespace Space2 { + struct Space1::A { + void x(); + } + } + + will now error out with: + + cpp_class_definition.i:5: Error: 'Space1::A' resolves to 'Space1::A' and + was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'. + + Previously some symbols would have been instantiated in the wrong scope and led + to lots of scope problems involving SWIG typemaps, features, renames etc. + You will need to correct the scope used in other SWIG directives which do not + support 'using declarations' and 'using directives'. For example, if you previously had: + + %rename(Zap) vector::clear; + using namespace std; + %template(VectorInt) vector; + + Prior versions of SWIG incorrectly instantiated vector in the global namespace + and so the %rename matched. Now the template is instantiated in the correct namespace, + so is fully qualified as std::vector. The other SWIG directives need correcting as + they do not follow 'using declarations' and 'using directives'. Change it to: + + %rename(Zap) std::vector::clear; + using namespace std; + %template(vin) vector; + + + *** POTENTIAL INCOMPATIBILITY *** + +2017-08-16: wsfulton + Fix scope lookup for template parameters containing unary scope operators. + + Fixes cases like: + + namespace Alloc { + template struct Rebind { + typedef int Integer; + }; + } + %template(RebindBucket) Alloc::Rebind< Bucket >; + OR + %template(RebindBucket) Alloc::Rebind< ::Bucket >; + + Alloc::Rebind< Bucket >::Integer Bucket1(); + Alloc::Rebind< ::Bucket >::Integer Bucket2(); + Alloc::Rebind<::template TemplateBucket>::Integer Bucket3(); + +2017-08-16: wsfulton + For templates only, the template parameters are fully resolved when + handling typemaps. Without this, it is too hard to have decent rules + to apply typemaps when parameter types are typedef'd and template + parameters have default values. + + Fixes %clear for typedefs in templates, eg: + + %typemap("in") XXX::Long "..." + template typename struct XXX { + typedef long Long; + }; + %clear XXX::Long; + + as the typemap was previously incorrectly stored as a typemap for long + instead of XXX::Long. + +2017-08-05: olly + [C++11] Allow static_assert at the top level (and disallow it right + after template). Fixes issue 1031 reported by Artem V L. + +2017-08-02: wsfulton + Fix incorrectly shown warning when an empty template instantiation was used on a + class used as a base class and that base class was explicitly ignored with %ignore. + Example of the warning which will no longer appear: + + Warning 401: Base class 'Functor< int,int >' has no name as it is an empty + template instantiated with '%template()'. Ignored. + +2017-07-17: fflexo + [Java] #674 Add std_list.i to add support for std::list containers. The Java proxy + extends java.util.AbstractSequentialList and makes the C++ std::list container look + and feel much like a java.util.LinkedList from Java. + +2017-07-07: wsfulton + [Python] Fix display of documented template types when using the autodoc + feature. For example when wrapping: + + %feature("autodoc"); + template struct T {}; + %template(TInteger) T; + + the generated documentation contains: + """Proxy of C++ T< int > class.""" + instead of: + """Proxy of C++ T<(int)> class.""" + and + """__init__(TInteger self) -> TInteger""" + instead of + """__init__(T<(int)> self) -> TInteger""" + +2017-06-27: nihaln + [PHP] Update the OUTPUT Typemap to add return statement to the + PHP Wrapper. + +2017-06-27: nihaln + [PHP] Update the enum and value examples to use the OO wrappers + rather than the flat functions produced with -noproxy. There's + not been a good reason to use -noproxy for since PHP5 OO wrapping + was fixed back in 2005. + +2017-06-23: m7thon + [Python] fix and improve default argument handling: + + 1. Fix negative octals. Currently not handled correctly by `-py3` + (unusual case, but incorrect). + 2. Fix arguments of type "octal + something" (e.g. `0640 | 04`). + Currently drops everything after the first octal. Nasty! + 3. Fix bool arguments "0 + something" (e.g. `0 | 1`) are always + "False" (unusual case, but incorrect). + 4. Remove special handling of "TRUE" and "FALSE" from + `convertValue` since there's no reason these have to match + "true" and "false". + 5. Remove the Python 2 vs. Python 3 distinction based on the + `-py3` flag. Now the same python code is produced for default + arguments for Python 2 and Python 3. For this, octal default + arguments, e.g. 0644, are now wrapped as `int('644', 8)`. This + is required, as Python 2 and Python 3 have incompatible syntax + for octal literals. + + Fixes #707 + +2017-06-21: futatuki + #1004 - Fix ccache-swig executable name to respect configure's --program-prefix and + --program-suffix values if used. + +2017-06-21: tamuratak + [Ruby] #911 - Add std::wstring support. + +2017-06-19: wsfulton + [Python] Fix handling of rich comparisons when wrapping overloaded operators: + + operator< operator<= operator> operator>= operator== operator!= + + Previously a TypeError was always thrown if the type was not correct. NotImplemented + is now returned from these wrapped functions if the type being compared with is + not correct. The subsequent behaviour varies between different versions of Python + and the comparison function being used, but is now consistent with normal Python + behaviour. For example, for the first 4 operator overloads above, a TypeError + 'unorderable types' is thrown in Python 3, but Python 2 will return True or False. + NotImplemented should be returned when the comparison cannot be done, see PEP 207 and + https://docs.python.org/3/library/constants.html#NotImplemented + + Note that the bug was only present when overloaded operators did not also have a + function overload. + + Fixes SF bug #1208 (3441262) and SF patch #303. + + *** POTENTIAL INCOMPATIBILITY *** + +2017-06-17: fabrice102 + [Go] Fix Go callback example. Fixes github #600, #955, #1000. + +2017-06-16: wsfulton + Make sure warning and error messages are not split up by other processes writing to + stdout at the same time. + +2017-06-16: wsfulton + [R] Fix wrapping function pointers containing rvalue and lvalue reference parameters. + +2017-06-13: olly + [Perl] Fix testsuite to work without . in @INC - it was removed in + Perl 5.26 for security reasons, and has also been removed from + older versions in some distros. Fixes #997 reported by lfam. + +2017-06-03: wsfulton + Fix %import on a file containing a file scope %fragment forced inclusion to not + generate the fragment contents as %import should not result in code being generated. + The behaviour is now the same as importing code insertion blocks. + Wrapping FileC.i in the following example will result in no generated code, whereas + previously "#include " was generated: + + // FileA.i + %fragment("", "header") %{ + #include + %} + + %{ + #include + %} + %fragment(""); + + // FileC.i + %import "FileA.i" + + *** POTENTIAL INCOMPATIBILITY *** + +2017-05-26: Volker Diels-Grabsch, vadz + [Java] #842 Extend from java.util.AbstractList<> and implement java.util.RandomAccess for + std::vector wrappers. This notably allows to iterate over wrapped vectors in a natural way. + Note that boxed types are now used in the Java layer when wrapping vector of C primitive + types, for example. This may introduce some subtle incompatibilities due to some + differences in how Java converts boxed types and unboxed types. For example, + + int i=0; + double d1 = i; // ok + Double d2 = i; // error: incompatible types: int cannot be converted to Double + + This can be a problem when calling the add and set functions. A suggested backwards + compatible workaround is to use something like (shown for std::vector: + + #if defined(SWIGJAVA) + // Add in old api that uses non-boxed types + %extend std::vector { + %proxycode %{ + public void add(double x) { + add(Double.valueOf(x)); + } + public void set(int i, double val) { + set(i, Double.valueOf(val)); + } + %} + } + #endif + + %include "std_vector.i" + %template(VectorDouble) std::vector; + + *** POTENTIAL INCOMPATIBILITY *** + +2017-05-30: davidcl + [Scilab] #994 Undefined symbol error when loading in Scilab 6 + +2017-05-25: asibross + [Java] #370 #417 Missing smart pointer handling in Java director extra methods + swigReleaseOwnership() and swigTakeOwnership(). + +2017-05-23: wsfulton + [Java] #230 #759 Fix Java shared_ptr and directors for derived classes java compilation + error. + + For shared_ptr proxy proxy classes, add a protected method swigSetCMemOwn for modifying + the swigCMemOwn and swigCMemOwnDerived member variables which are used by various other + methods for controlling memory ownership. + +2017-05-21: Sghirate + [Java, C#, D] #449 Remove unnecessary use of dynamic_cast in directors to enable + non-RTTI compilation. + +2017-05-21: wsfulton + [Python] #993 Fix handling of default -ve unsigned values, such as: + void f(unsigned = -1U); + +2017-05-20: jschueller + [Python] #991 Fix E731 PEP8 warning: do not assign a lambda expression + +2017-05-16: nihal95 + [PHP] Add %pragma version directive to allow the version of the + extension to be set. Patch #970, fixes #360. + +2017-05-13: yag00 + Patch #975 - Add support for noexcept on director methods. + +2017-04-27: redbrain + Issue #974, Patch #976 - Fix preprocessor handling of macros with commas in a comment. + +2017-04-25: jleveque + [Lua] #959 - Fix Visual Studio C4244 conversion warnings in Lua wrappers. + +2017-04-21: tamuratak + [Ruby] #964 - Add shared_ptr director typemaps. + +2017-04-20: wsfulton + [Ruby] #586, #935 Add assert for invalid NULL type parameter when calling SWIG_Ruby_NewPointerObj. + +2017-04-20: tamuratak + [Ruby] #930, #937 - Fix containers of std::shared_ptr. + Upcasting, const types (eg vector>) and NULL/nullptr support added. + +2017-04-12: smarchetto + [Scilab] New parameter targetversion to specify the Scilab target version (5, 6, ..) for code generation + With Scilab 6 target specified, identifier names truncation is disabled (no longer necessary) + +2017-03-24: tamuratak + [Ruby] Fix #939 - Wrapping std::vector fix due to incorrect null checks + on VALUE obj. + +2017-03-17: vadz + [C#] #947 Add support for std::complex + +2017-03-17: wsfulton + [Go] Fix handling of typedef'd function pointers and typedef'd member function pointers + such as: + + typedef int (*FnPtr_td)(int, int); + int do_op(int x, int y, FnPtr_td op); + +2017-03-16: wsfulton + Add support for member const function pointers such as: + + int fn(short (Funcs::* parm)(bool)) const; + + Also fix parsing of references/pointers and qualifiers to member + pointers such as: + + int fn(short (Funcs::* const parm)(bool)); + int fn(short (Funcs::* & parm)(bool)); + +2017-03-10: wsfulton + Extend C++11 alternate function syntax parsing to support const and noexcept, such as: + + auto sum1(int x, int y) const -> int { return x + y; } + auto sum2(int x, int y) noexcept -> int { return x + y; } + +2017-02-29: tamuratak + [Ruby] #917 - Add Enumerable module to all container class wrappers. It was missing + for std::list, std::multiset, std::unordered_multiset and std::unordered_map. + +2017-02-27: assambar + [C++11] Extend parser to support throw specifier in combination + with override and/or final. + +2017-02-10: tamuratak + [Ruby] #883 - Add support for C++11 hash tables: + std::unordered_map + std::unordered_set + std::unordered_multimap + std::unordered_multiset + +2017-02-08: jcsharp + [C#] #887 Improve std::vector wrapper constructors - + Replace constructor taking ICollection with IEnumerable and also add IEnumerable + constructor to avoid the boxing and unboxing overhead of the original constructor, + when the type parameter is a value type. + +Version 3.0.12 (27 Jan 2017) +============================ + +2017-01-27: wsfulton + [C#] #882 Fix missing filename in error messages when there is a problem + writing out C# files. + +2017-01-27: briancaine + [Guile] #744 Fix compilation errors in Guile wrappers - regression + introduced in swig-3.0.11. + +2017-01-24: andrey-starodubtsev + [Java] Apply #704 - director typemap improvements. + Memory leak fixes, add support for "directorargout" typemap and + add director support to typemaps.i. + +2017-01-24: wsfulton + Enhance %extend to extend a class with template constructors, eg: + + struct Foo { + %extend { + template + Foo(int a, T b) { + ... + } + } + }; + %template(Foo) Foo::Foo; + +2017-01-22: wsfulton + Issue #876 Enhance %extend to extend a class with template methods, eg: + + struct Foo { + %extend { + template + void do_stuff(int a, T b) { + ... + } + } + }; + %template(do_stuff_inst) Foo::do_stuff; + + Similarly for static template methods. + +2017-01-22: kwwette + [Octave] add support for version 4.2 + - The Octave API now uses some C++11 features. It is recommended to use + the mkoctfile program supplied by Octave to compile the SWIG-generated + wrapper code, as mkoctfile will ensure the correct C++ compiler/options + are used. Otherwise, the value of `mkoctfile -p CXX` should be parsed + for any -std=* flags which might be present. + - Octave has dropped support for << and >> operators, so SWIG now + ignores them. + - The Octave error() function now raises C++ exceptions to propagate + Octave errors, so %exception directives may need to be modified. + For convenience the SWIG_RETHROW_OCTAVE_EXCEPTIONS macro can be used + to rethrow any Octave exceptions for Octave itself to handle, e.g.: + + try { + $action // may call error() + } + SWIG_RETHROW_OCTAVE_EXCEPTIONS // error() exceptions are rethrown + catch(...) { + ... // all other exceptions + } + + *** POTENTIAL INCOMPATIBILITY *** + +2017-01-16: wkalinin + [C#] Fix #733 regression introduced in swig-3.0.9. + Missing virtual function override in C# layer when using %import. + +2017-01-16: fschlimb + Fix #813 template symbol name lookup bug when typedef names are the same but in different + namespaces. + +2017-01-15: wsfulton + [C# D Java] + The SWIG library no longer uses the javatype, dtype or cstype typemaps, thereby + completely freeing them up for users to use without having to replicate the library + code that they previously added. The code previously generated by these typemaps + has been replaced by the new %proxycode directive. Their use in the library code + was fairly minimal: + + C# cstype: std_array.i std_map.i std_vector.i + D dtype: std_vector.i + Java javatype: arrays_java.i + +2017-01-14: wsfulton + The %extend directive can now optionally support one of the 'class', 'struct' or 'union' + keywords before the identifier name, for example: + + struct X { ... }; + %extend struct X { ... } + + Previously this had to specified as: + + struct X { ... }; + %extend X { ... } + +2017-01-13: wsfulton + [C# D Java] Add new %proxycode directive which is a macro for %insert("proxycode"). + This is a way of adding pure C#/D/Java code into the appropriate proxy class, eg: + + %extend Proxy2 { + %proxycode %{ + public int proxycode2(int i) { + return i+2; + } + %} + } + + %inline %{ + struct Proxy2 {}; + %} + + There will then be a pure Java/C#/D method called proxycode2 in the Proxy2 class. + +2016-12-31: ajrheading1 + Issue #860 - Remove use of std::unary_function and std::binary_function + which is deprecated in C++11. + +2016-12-30: olly + [PHP7] Register internal 'swig_runtime_data_type_pointer' constant + as "CONST_PERSISTENT" to avoid segmentation fault on module unload. + Fixes #859 reported by Timotheus Pokorra. Thanks also to Javier Torres + for a minimal reproducer. + +Version 3.0.11 (29 Dec 2016) +============================ + +2016-12-24: wsfulton + [C#] Add %feature("csdirectordelegatemodifiers") to enable customization + of the delegate access modifiers generated in director classes. + Fixes issue #748. + +2016-12-23: wsfulton + [Python] Fix builtin "python:slot" feature failing for tp_hash when using + hashfunc closure with a "Wrong type for hash function" for Python 2. + Issue #843. + +2016-12-21: joequamt + Changed generation of functions so that only functions + that end in _set generate accessor functions rather than + looking for "set". + Change generation of operators to not have underscores + to start in R. Users need to provide custom names for these operator overloads. + +2016-12-21: olly + Fix isfinite() checks to work with all C++11 compilers. + Fixes issues #615, #788 and #849. + +2016-12-20: wsfulton + %namewarn unnecessarily caused keyword warnings for non-instantiated template classes + and duplicate warnings for instantiated template classes when keywords were used. + Issue #845. + +2016-12-18: ezralanglois + [Python, Ruby, Octave] Memory leak fix on error in std::pair wrappers. + Issue #851. + +2016-12-18: wsfulton + Zero initialize arrays when using %array_class and %array_functions. + +2016-12-18: t-ikegami + [Python] Fix #446 + Python %array_class of carrays.i failed with -builtin option. + +2016-12-16: briancaine + [Guile] Patch #744 Added support for Guile's native pointer functionality + +2016-12-01: wsfulton + [Python] Issue #769. + Add optional moduleimport attribute to %module so that the + default module import code can be overridden. See the "Searching for the wrapper module" + documentation in Python.html. Example: + + %module(moduleimport="import _foo") foo + + $module also expands to the low-level C/C++ module name, so the following is the + same as above + + %module(moduleimport="import $module") foo + +2016-11-30: olly + [PHP] Add support for PHP7. PHP5's C extension API has changed + substantially so you need to use -php7 to specify you want PHP7 + compatible wrappers. The default extension for generated wrappers + is now .cxx (to match SWIG's default for every other language - to + generate foo_wrap.cpp you can run SWIG with -cppext cpp). Fixes + issue #571. + + As part of this change, the language subdirectory for PHP5 has + changed from "php" to "php5" - if you are making use of the search + path feature where the language subdirectory of each directory + is also searched, you'll need to update your bindings. A simple + fix which works for older and newer SWIG is to add a symlink: + ln -s php php5 + + *** POTENTIAL INCOMPATIBILITY *** + +2016-11-30: olly + [PHP] Only emit one copy of each distinct arginfo. Previously we + emitted a separate one for every wrapped function, but typically + many functions have the same number of parameters and combinations + of parameters passed by reference or not. + + This change significantly reduces both the size of the generated + wrapper, and of the compiled PHP extension module (e.g. by ~6% for + the stripped extension module for Xapian's PHP7 bindings). + +2016-11-28: wsfulton + Fix %rename override of wildcard %rename for templates. For example: + + %rename(GlobalIntOperator) *::operator bool; // wildcard %rename + + %rename(XIntOperator) X::operator bool; // fix now overrides first %rename above + OR + %rename(XIntOperator) X::operator bool; // fix now overrides first %rename above + + template struct X { + operator bool(); + ... + }; + %template(Xint) X; + + This also fixes %rename override of global %rename for templates. For example: + + // Global rename to make all functions start with a lower case letter + %rename("%(firstlowercase)s", %$isfunction ) ""; + %rename(woohoo) W::Woo; // fix now overrides above %rename + + template struct W { + W Woo(); + ... + }; + %template(Wint) W; + + The above also introduces a possibly unexpected change. Many of the STL containers + provided by SWIG use %rename to rename some methods, eg in std::vector, push_back + is renamed to add in Java. Previously this intended rename did not happen when using + using global %rename rules and the method would remain as push_back, but is now + renamed to add. Some more info in issue #856. + + *** POTENTIAL INCOMPATIBILITY *** + +2016-11-26: m7thon + [Python] Issue #709 - improved wrapping of division operators + 'from __future__ import division' now works in Python 2 whether or not the + -py3 flag is used. + +2016-11-12: joequant + [R] Issue #697 - fix comma issue with overload methods + +2016-11-12: joequant + [R] Issue #555 - R runtime needs stdio.h + +2016-11-02: wsfulton + [Python] Issue #816 - fix compilation error when using -extranative and -builtin. + +2016-11-02: liorgold + Patch #741 - Add support for C++11 alias templates, see updated CPlusPlus11.html + documentation. + +2016-10-30: myd7349 + [C#] Patch #740 Add std_array.i for C# for wrapping std::array. + + Patch also enhances std::vector C# wrappers with additional functions + (Contains, IndexOf, LastIndexOf and Remove). + +2016-10-30: tobilau + [Java] Fix wrappers for wstring parameters in director methods to cleanup local + ref after director callback has finished. + +2016-10-23: wsfulton + [C#] Add missing csdirectorin VOID_INT_PTR and csdirectorout VOID_INT_PTR typemaps. + +2016-10-23: jiulongw + Patch #781 - Fix wrapping of C compound expressions containing char constants + in quotes such as: + + #define H_SUPPRESS_SCALING_MAGIC (('s'<<24) | ('u'<<16) | ('p'<<8) | 'p') + + enum DifferentTypes { + typecharcompound='A'+1, + typecharcompound2='B' << 2 + }; + +2016-10-13: wsfulton + [Python] Issue #808 - fix Python pickling and metaclass for builtin wrappers. + + The metaclass (SwigPyObjectType) for SWIG objects was not defined in + a way that let importlib successfully import the Python wrappers. + The pickle module previously failed to pickle objects because it couldn't + determine what module the SWIG wrapped objects were in. + +2016-09-29: wsfulton + [Allegrocl, CFFI, GO, Javascript, Ocaml, R, Scilab] + Add missing support for the "ret" typemap in a few target languages. + The documentation also now has info on the "ret" typemap. + +2016-09-27: ahmed-usman + [xml] Handle template parameters correctly. + +2016-09-27: dontpanic92 + [Go] Fix argument names in inherited functions taking more than 8 + parameters. Fixes #795. + +2016-09-26: smarchetto + [Scilab] mlists that map pointers can be given a custom type name. + +2016-09-25: wsfulton + Patch #793 from q-p to expand exception handling to include std::bad_cast + in std_except.i. + +2016-09-24: olly + [PHP] Fix code generated for feature("director:except") - + previously the return value of call_user_function() was ignored and + we checked an uninitialised value instead. Fixes #627. Based on + patch from Sergey Seroshtan. + +2016-09-22: wsfulton + [Python] More flexible python builtin slots for overloaded C++ function. + + The closure names used for builtin slots are mangled with their functype so + that overloaded C++ method names can be used for multiple slots. + For example: + + %feature("python:slot", "mp_subscript", functype="binaryfunc") SimpleArray::__getitem__; + %feature("python:slot", "sq_item", functype="ssizeargfunc") SimpleArray::__getitem__(Py_ssize_t n); + + will generate closures: + + SWIGPY_SSIZEARGFUNC_CLOSURE(_wrap_SimpleArray___getitem__) /* defines _wrap_SimpleArray___getitem___ssizeargfunc_closure */ + SWIGPY_BINARYFUNC_CLOSURE(_wrap_SimpleArray___getitem__) /* defines _wrap_SimpleArray___getitem___binaryfunc_closure */ + + Previously only one name was defined: _wrap_SimpleArray___getitem___closure. + Hence the overloaded __getitem__ method can be used to support both mp_subscript and sq_item slots. + +2016-09-17: wsfulton + [Python] Fix iterators for containers of NULL pointers (or Python None) when using + -builtin. Previously iteration would stop at the first element that was NULL. + +2016-09-16: olly + [Javascript] Fix SWIG_exception() macro to return from the current + function. Fixes #789, reported by Julien Dutriaux. + +2016-09-16: olly + [PHP] Fix SWIG_exception() macro to return from the current function. + Fixes #240, reported by Sergey Seroshtan. + +2016-09-12: xypron + [C#] Patch #786 Keyword rename to be CLS compliant by adding an underscore + suffix instead of an underscore prefix to the C symbol name. Please use an explicit + %rename to rename the symbol with a _ prefix if you want the old symbol name. + + *** POTENTIAL INCOMPATIBILITY *** + +2016-09-09: olly + [Python] Fix import handling for Python 2.6 to work in a frozen + application. Fixes #145, reported by Thomas Kluyver. + +2016-09-02: smarchetto + [Scilab] Pointers are mapped to mlist instead of tlist + (mlist better for scilab overloading) + +2016-09-02: olly + [PHP] Fix "out" typemap for member function pointers and "in" + typemap for char INPUT[ANY]. + +2016-09-01: wsfulton + [Python] More efficient Python slicing. + Call reserve for container types that support it to avoid repeated + memory reallocations for new slices or slices that grow in size. + +2016-09-01: wsfulton + [Python] #771 - Make builtin types hashable by default. + Default hash is the underlying C/C++ pointer. This matches up with testing for + equivalence (Py_EQ in SwigPyObject_richcompare) which compares the pointers. + +2016-08-22: wsfulton + [Python] The following builtin slots can be customized like other slots via the + "python:" and "python:slot" features where is the appropriate slot name: + tp_allocs + tp_bases + tp_basicsize + tp_cache + tp_del + tp_dealloc + tp_flags + tp_frees + tp_getset + tp_is_gc + tp_maxalloc + tp_methods + tp_mro + tp_new + tp_next + tp_prev + tp_richcompare + tp_subclasses + tp_weaklist + was_sq_ass_slice + was_sq_slice + + A few documentation improvements for slot customization. + +2016-08-09: joequant + [R] Patch #765 Fix extern "C" header includes for C++ code. + +2016-08-05: olly + [xml] Fix how the output filename is built to avoid problems when + it contains the embedded strings ".c", ".cpp" or ".cxx". + Fixes #540 reported by djack42. + +2016-07-01: wsfulton + Fix corner case of wrapping std::vector of T pointers where a pointer to a pointer of T + also exists in the wrapped code. SF Bug 2359417 (967). + +2016-06-26: wkalinin + [Java, C#] Patch #681 Fix seg fault when ignoring nested classes. + +2016-06-25: mromberg + [Python] #711 Fix -castmode and conversion of signed and unsigned integer types. + See 2015-12-23 CHANGES entry for details of these improvements when they were + implemented for the default options (ie not using -castmode). + +2016-06-25: ahnolds + Patch #730 - Fix %implicitconv for overloaded functions when using + -castmode or -fastdispatch options. + + The result is that in all overload cases where there are multiple possibilities + with the same number of arguments, the dispatch function will first check for + exact (aka non implicit) matches, and then subsequently check for implicit + casting matches. This was already happening in the normal dispatch situation, + and in the -fastdispatch case two passes through the candidates were happening, + just with SWIG_POINTER_IMPLICIT_CONV always set. After this patch, it is not set + on the first pass, and then set on the second pass. + +2016-06-25: liorgold + Patch #727 - Add support for C++11 type aliasing. Version 3.0.10 (12 Jun 2016) ============================ @@ -177,7 +2156,7 @@ Version 3.0.9 (29 May 2016) 2016-03-01: olly Fix isfinite() check to work with GCC6. Fixes - https://github.com/swig/swig/issues/615 reported by jplesnik. + issue #615 reported by jplesnik. 2016-02-17: olly [Python] Add missing keywords 'as' and 'with' to pythonkw.swg. @@ -234,7 +2213,7 @@ Version 3.0.9 (29 May 2016) 2016-01-12: olly [Javascript] For v8 >= 4.3.0, use V8_MAJOR_VERSION. - Fixes https://github.com/swig/swig/issues/561. + Fixes issue 561. 2016-01-10: ahnolds Improved size_t and ptrdiff_t typemaps to support large values @@ -11161,7 +13140,7 @@ Version 1.3.23 (November 11, 2004) - Properly qualify type in syntax as 'long(2)' or 'Foo()', this solve old problem with default args, and probably other problems around. However, the default arg problem - was also already solved by William (see bellow). + was also already solved by William (see below). - Fix feature_set and feature_get methods. Before they look from particular to general and keep the first @@ -11369,7 +13348,7 @@ Version 1.3.23 (November 11, 2004) ie, no additional pointer elements are created, and the original 'foo' and 'A.bar' can be used as parameters. - In the case of member fucntion however, still you need + In the case of member function however, still you need to use the special variable Class::_cb_ptr, ie: foobarm(3, a, A.barm_cb_ptr) @@ -20672,7 +22651,7 @@ Version 1.3.7 (September 3, 2001) typedef __name vector; %enddef - An a specific instantiation is created in exactly the same way: + A specific instantiation is created in exactly the same way: %template(intvec) vector; diff --git a/CHANGES.current b/CHANGES.current index f6fee14ca..3b9634726 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,97 +1,72 @@ Below are the changes for the current release. See the CHANGES file for changes in older releases. See the RELEASENOTES file for a summary of changes in each release. +Issue # numbers mentioned below can be found on Github. For more details, add +the issue number to the end of the URL: https://github.com/swig/swig/issues/ -Version 3.0.11 (in progress) -============================ +Version 4.0.1 (in progress) +=========================== -2016-09-12: xypron - [C#] Patch #786 Keyword rename to be CLS compliant by adding an underscore - suffix instead of an underscore suffix to the C symbol name. Please use an explicit - %rename to rename the symbol with a _ prefix if you want the old symbol name. +2019-07-23: smithx + [C#] #1530 #1532 Fix marshalling of std::wstring to C#. + +2019-07-18: gicmo + [Python] #1587 Python 3.8 support - remove use of deprecated PyObject_GC_UnTrack. + +2019-07-18: cher-nov + [Python] #1573 Generated Python code uses consistent string quoting style - double + quotes. + +2019-07-16: geefr + [C#] #616 #1576 Fix C# bool INPUT[], bool OUTPUT[], bool INOUT[] typemaps to marshall + as 1-byte. + +2019-07-12: vadz + [C#, Java] #1568 #1583 Fix std::set<> typemaps for primitive types. + +2019-07-12: vadz + #1566 #1584 Regression in 4.0.0 - fix missing value for first item of enums with + trailing comma. + +2019-07-11: mcfarljm + #1548 #1578 Fix segfault in Doxygen parser parsing empty lines in some commands like + \code. + +2019-07-09: IsaacPascual + [C#, Java] #1570 Fix name of generated C#/Java classes for %interface macros + in swiginterface.i when wrapping nested C++ classes. + +2019-07-05: wsfulton + [Python] #1547 Whitespace fixes in Doxygen translated comments into pydoc comments + for Sphinx compatibility. + +2019-06-28: wsfulton + [MzScheme, OCaml] #1559 $arg and $input were incorrectly substituted in the + argout typemap when two or more arguments were present. + +2019-06-24: wsfulton + [Python, Ruby] #1538 Remove the UnknownExceptionHandler class in order to be + C++17 compliant as it uses std::unexpected_handler which was removed in C++17. + This class was intended for director exception handling but was never used by + SWIG and was never documented. *** POTENTIAL INCOMPATIBILITY *** -2016-09-09: olly - [Python] Fix import handling for Python 2.6 to work in a frozen - application. Fixes #145, reported by Thomas Kluyver. +2019-06-06: bkotzz + [Java] #1552 Improve performance in Java std::vector constructor wrapper that takes + a native Java array as input. -2016-09-02: smarchetto - [Scilab] Pointers are mapped to mlist instead of tlist - (mlist better for scilab overloading) +2019-06-03: olly + [Python] Fix regression in implicit_conv handling of tuples, + introduced in SWIG 4.0.0. Fixes #1553, reported by Alexandre + Duret-Lutz. -2016-09-02: olly - [PHP] Fix "out" typemap for member function pointers and "in" - typemap for char INPUT[ANY]. +2019-05-24: wsfulton + [Octave] Fix detection of Octave on MacOS. -2016-09-01: wsfulton - [Python] More efficient Python slicing. - Call reserve for container types that support it to avoid repeated - memory reallocations for new slices or slices that grow in size. +2019-05-24: opoplawski + [Octave] #1522 Adapt OCTAVE_LDFLAGS for Octave 5.1. -2016-09-01: wsfulton - [Python] #771 - Make builtin types hashable by default. - Default hash is the underlying C/C++ pointer. This matches up with testing for - equivalence (Py_EQ in SwigPyObject_richcompare) which compares the pointers. - -2016-08-22: wsfulton - [Python] The following builtin slots can be customized like other slots via the - "python:" and "python:slot" features where is the appropriate slot name: - tp_allocs - tp_bases - tp_basicsize - tp_cache - tp_del - tp_dealloc - tp_flags - tp_frees - tp_getset - tp_is_gc - tp_maxalloc - tp_methods - tp_mro - tp_new - tp_next - tp_prev - tp_richcompare - tp_subclasses - tp_weaklist - was_sq_ass_slice - was_sq_slice - - A few documentation improvements for slot customization. - -2016-08-09: joequant - [R] Patch #765 Fix extern "C" header includes for C++ code. - -2016-08-05: olly - [xml] Fix how the output filename is built to avoid problems when - it contains the embedded strings ".c", ".cpp" or ".cxx". - Fixes #540 reported by djack42. - -2016-07-01: wsfulton - Fix corner case of wrapping std::vector of T pointers where a pointer to a pointer of T - also exists in the wrapped code. SF Bug 2359417 (967). - -2016-06-26: wkalinin - [Java, C#] Patch #681 Fix seg fault when ignoring nested classes. - -2016-06-25: mromberg - [Python] #711 Fix -castmode and conversion of signed and unsigned integer types. - See 2015-12-23 CHANGES entry for details of these improvements when they were - implemented for the default options (ie not using -castmode). - -2016-06-25: ahnolds - Patch #730 - Fix %implicitconv for overloaded functions when using - -castmode or -fastdispatch options. - - The result is that in all overload cases where there are multiple possibilities - with the same number of arguments, the dispatch function will first check for - exact (aka non implicit) matches, and then subsequently check for implicit - casting matches. This was already happening in the normal dispatch situation, - and in the -fastdispatch case two passes through the candidates were happening, - just with SWIG_POINTER_IMPLICIT_CONV always set. After this patch, it is not set - on the first pass, and then set on the second pass. - -2016-06-25: liorgold - Patch #727 - Add support for C++11 type aliasing. +2019-05-22: ferdynator + [PHP] #1528 Don't add a closing '?>' PHP tag to generated files. + PSR-2 says it MUST be omitted for files containing only PHP. diff --git a/COPYRIGHT b/COPYRIGHT index 18fc892ba..c9b8c1a47 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -20,6 +20,7 @@ Active SWIG Developers: Oliver Buchtala (oliver.buchtala@gmail.com) (Javascript) Neha Narang (narangneha03@gmail.com) (Javascript) Simon Marchetto (simon.marchetto@scilab-enterprises.com) (Scilab) + Zackery Spytz (zspytz@gmail.com) (OCaml, SWIG core) Past SWIG developers and major contributors include: Dave Beazley (dave-swig@dabeaz.com) (SWIG core, Python, Tcl, Perl) @@ -29,7 +30,7 @@ Past SWIG developers and major contributors include: Mikel Bancroft (mikel@franz.com) (Allegro CL) Surendra Singhi (efuzzyone@netscape.net) (CLISP, CFFI) Marcelo Matus (mmatus@acms.arizona.edu) (SWIG core, Python, UTL[python,perl,tcl,ruby]) - Art Yerkes (ayerkes@speakeasy.net) (Ocaml) + Art Yerkes (ayerkes@speakeasy.net) (OCaml) Lyle Johnson (lyle@users.sourceforge.net) (Ruby) Charlie Savage (cfis@interserv.com) (Ruby) Thien-Thi Nguyen (ttn@glug.org) (build/test/misc) @@ -63,7 +64,8 @@ Past SWIG developers and major contributors include: John Lenz (Guile, MzScheme updates, Chicken module, runtime system) Baozeng Ding (Scilab) Ian Lance Taylor (Go) - Vadim Zeitlin (PCRE, Python) + Dmitry Kabak (userdima@gmail.com) (Doxygen) + Vadim Zeitlin (PCRE, Python, Doxygen) Stefan Zager (szager@gmail.com) (Python) Vincent Couvert (Scilab) Sylvestre Ledru (Scilab) diff --git a/Doc/Devel/cpp11.html b/Doc/Devel/cpp11.html deleted file mode 100644 index fc35465ae..000000000 --- a/Doc/Devel/cpp11.html +++ /dev/null @@ -1,788 +0,0 @@ - - - - - - - - - - - - - - - -

C++0x/C++11 support for SWIG

-

Summary

-

This is a technical overview of the C++0x/C++11 support for the Swig. -This area of Swig is a work in progress. Initial C++0x/C++11 support for -Swig was written during the Google Summer of Code 2009 period by -MatevĹľ Jekovec.

-

SVN branch

-

branches/gsoc2009-matevz

-

New C++11 features status

-

Wikipedia article: http://en.wikipedia.org/wiki/C%2B%2B0x -

-

Rvalue reference and move semantics [done]

-

The Rvalues are used in practice to speed up the move operations -on different containers.

-

In the following example, we want to swap the given elements:

-
template <class T> swap(T& a, T& b) {
-    T tmp(a);   // now we have two copies of a
-    a = b;      // now we have two copies of b
-    b = tmp;    // now we have two copies of tmp (aka a)
-}

-This can now be solved using the new function std::move():

-
template <class T> swap(T& a, T& b) {
-    T tmp(std::move(a));
-    a = std::move(b);   
-    b = std::move(tmp);
-}

-For the move function to take effect, user needs to reimplement the -move constructor (taking ClassType&& as an argument) and -operator=(ClassType&&):

-
class MyClass {
-  MyClass(MyClass&& p) : ptr(p.ptr) {p.ptr = 0;}
-  MyClass& operator=(MyClass&& p) {
-    std::swap(ptr, p.ptr);
-    return *this;
-  }
-};

-In practice, the Rvalues are used for temporaries (when passing the -result of one function as an argument to another).

-

Done: Added type&& to Swig parser. Added testcase -cpp11_rvalue_reference.i. Operator && is treated the same as -operator &. R11450

-

Article: -http://www.artima.com/cppsource/rvalue.html

-

Generalized constant expressions [done]

-

In C++11 you can define functions as constant expressions. -Functions need to return constant value in form "return expr", -where expr is a constant expression. -

-

A keyword "constexpr" is introduced for this. eg.: -constexpr int getNumber() { return 5; } const int MY_CONSTANT = -getNumber(); -

-

Constants are treated as normal variables in interpreted languages -because they are not compiled into the executable. Java "final" -constants are defined runtime as well. C++ constants need to be -declared in the header file and defined in the implementation file, -so swig doesn't need to know about the constant values when parsing -the header file. -

-

Done: Added the “constexpr “ keyword to Swig. Added testcase -cpp11_constexpr. R11322

-

Problem: No compilers were known to support constexpr yet, so the -testcase was temporarily commented out in common.mk. -

-

Extern template [done]

-

Extern template forces the GCC compiler to not instantiate the -template in the translation unit at that time. It's a feature -specifically aimed at compilers to speed up the compilation process. -

-

Done: Added support for 'extern template class -std::vector<MyClass>;'. Added testcase cpp11_template_explicit. -R11385 , R11386

-

Initializer lists [done]

-

Initializer list is a new type in standard library: -std::initializer_list<T>. New symbols {} are introduced for the -initializer lists. -

-

One can now use: -

-
 class A {
- public:
-   A( std::initializer_list<int> );
- };
- A a1 = {1,2,3,4};

-Languages like Java, C# and Python already support direct creation of -lists natively.

-

Problem: initializer_list cannot be treated as an ordinary list. -The constructor containing initializer_list can only be accessed by -assigning the value using the {} brackets. I also don't think there -is a simple way to convert an ordinary list or a vector to the -initializer_list.

-

Done: Ignored the constructor having initializer_list as its -argument. Show warning to the user. Added testcase -cpp11_initializer_list. R11450

-

Article: -http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1919.pdf

-

Uniform initialization [done]

-

The new C++11 standard will allow the following:

-
struct IdString {
-  std::string name;
-  int identifier;
-};
- 
-IdString GetString() {
-  return {"SomeName", 4}; //Note the lack of explicit type.
-}

-The feature works exactly as it did now for POD types only (eg. int -a[] = {1,2,3};). The following declarations are the same in the new -C++11:

-
IdString str1 = {„SomeName“, 4};
-IdString str2{„SomeName“, 4};

-The new way of using uniform initialization allows the following:

-
struct BasicStruct {
- int x;
- double y;
-};
- 
-struct AltStruct {
-  AltStruct(int x, double y) : x_{x}, y_{y} {}
- 
-private:
-  int x_;
-  double y_;
-};
- 
-BasicStruct var1{5, 3.2}; // only fills the struct components
-AltStruct var2{2, 4.3};   // calls the constructor

-The new syntax is specific to C++. Java, C# and scripting languages -do not support this behaviour, but always need constructors. They -support {} brackets for declaration of arrays as C does + they add -support for creation of arrays on-the-fly (what C++11 introduced with -this feature and more).

-

Done: Added syntax for {} member initialization in class -constructor. Added testcase cpp11_uniform_initialization. R11413

-

Type inference [partially done]

-

A new keyword 'auto' is introduced in C++11:

-
auto a1 = 100;
-auto a2 = myFunc();

-The type of a1 and a2 is automatically determined according to the -initialization value during the semantic phase of the compiler.

-

Another macro 'decltype()' is introduced. The macro takes the -concrete object as an argument and returns its type. User could use -this as:

-
int i = 100;
-decltype(i) j = 200; // decltype(i) = int

-Calling operators are allowed as well:

-
decltype(i+j) k = 300;

-Done: Added support for decltype() syntax. Test cases for normal -decltype members and alternate function members work fine. Currently -only syntax in form decltype(variable name) work. No support for -custom expresions eg. decltype(i+j) yet. R11525

-

TODO: William proposed to support the hidden variables as well -(ones not parsed by Swig and added to symbol table). This also allows -Swig to parse custom expressions like decltype(i+j). The idea is to -introduce a new SwigType for this.

-

Range-based for-loop [ignored]

-

This feature is always present inside the implementation block -only. -

-

Lambda functions and expressions [done]

-

C++11 introduces lambda functions defined as:

-
[](int x, int y) -> int { return x + y; }

-If the lambda function contains a single return statement only or the -function doesn't return any type, the return type '->' can be -omitted. Lambda functions are function objects.

-

The following example prints the number of items stored in a list:

-
std::vector<int> someList;
-int total = 0;
-std::for_each( someList.begin(), someList.end(), [&total](int x) {total += x} );
-std::cout << total;

-Parameters inside the [] are the visible parameters of the lambda -functions. These can be & (references), = (copies), variable name -(variable copy), &variable name (variable reference) or this -(copy of the current object).

-

Lambda functions can be stored using:

-
auto myLambdaFunc = [this]() { this->SomePrivateMemberFunction() };

-Proposal: Lambda functions are most commonly used inside the function -block to quickly define how the sort, find and similar functions -should work (the other way would be overriding a class – the Java -style). The latest GCC does not support lambda functions yet so it is -difficult to test the feature once implemented. I would implement the -syntax support for this feature, but produce no wrapper code. Lambda -functions still work inside the function block though.

-

Article: -http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2550.pdf

-

Done: Added syntax support for the lambda functions. Added -testcase cpp11_lambda_functions.i. R11491, R11492

-

Alternate function syntax [done]

-

The problem with decltype() is that the parameters need to be -defined before the decltype. The following syntax is not valid, -because lhs and rhs hasn't been defined at the time of decltype:

-
template< typename LHS, typename RHS> 
-  decltype(lhs+rhs) AddingFunc(const LHS &lhs, const RHS &rhs) {return lhs + rhs;} //Not legal C++11

-The solution C++11 offers is the combination of the 'auto' keyword -before and '-> rettype' after the function declaration:

-
template< typename LHS, typename RHS> 
-  auto AddingFunc(const LHS &lhs, const RHS &rhs) -> decltype(lhs+rhs) {return lhs + rhs;}

-The new syntax only makes the job for the C++ compilers easier when -parsing such functions. The new syntax can be used for ordinary -functions as well:

-
struct SomeStruct {
-  auto FuncName(int x, int y) -> int;
-};
- 
-auto SomeStruct::FuncName(int x, int y) -> int {
-  return x + y;
-}

-Done: Added support for the 'auto' return type. Added support for the -'-> type' after the funtion declaration. Added testcases -cpp11_alternate_function_syntax.i and -cpp11_alternate_function_syntax_runme.py. R11414

-

Concepts, Axioms [ignored]

-

In C++ there is a common problem when you use a template in the -class which doesn't support all the operations the functions in the -class actually do on the type. Compiler errors are usually very long -and unreadable. C++11 adds support for the "concepts". The -idea is to define what operations and attributes should the template -have. In contrast to class inheritance and polimorphism, all lookups -are done in compile-time. -

-

Basic syntax (note LessThanComparable? -instead of "class" or "typename"): -

-
 template<LessThanComparable? T>
- const T& min(const T &x, const T &y) {
-   return y < x ? y : x;
- }

-Extended syntax (requires conditions are separated with &&, -|| or !): -

-
 template< typename T> requires LessThanComparable?<T>
- const T& min(const T &x, const T &y) {
-   return y < x ? y : x;
- }

-Definition of the concepts: -

-
 concept LessThanComparable?< typename T > {
-   bool operator<(T,T);
-   requires GreaterThanComparable?<T>;
-   typename value_type;
-   typename reference;
- };

-Concept maps allow usage of a specific type: -

-
 template< typename T>
- concept_map InputIterator?<T*> {
-   typedef T value_type ;
-   typedef T& reference ;
-   typedef T* pointer ;
-   typedef std::ptrdiff_t difference_type ;
- };

-Concept maps can act as mini-types, with function definitions and -other constructs commonly associated with classes: -

-
 concept Stack< typename X> {
-   typename value_type;
-   void push(X&, const value_type&);
-   void pop(X&);
-   value_type top(const X&);
-   bool empty(const X&);
- };
- template< typename T>
- concept_map Stack<std::vector<T> > {
-   typedef T value_type;
-   void push(std::vector<T>& v, const T& x) { v.push_back(x); }
-   void pop(std::vector<T>& v) { v.pop_back(); }
-   T top(const std::vector<T>& v) { return v.back(); }
-   bool empty(const std::vector<T>& v) { return v.empty(); }
- };

-Axioms are a facility pertaining to concepts supplied by C++11 to -express the semantic properties of concepts. For example, the concept -Semigroup can be defined with an axiom Associativity as: -

-
 concept Semigroup< typename Op, typename T> : CopyConstructible?<T> {
-   T operator()(Op, T, T);
-   axiom Associativity(Op op, T x, T y, T z) {
-     op(x, op(y, z)) == op(op(x, y), z);
-   }
- };

-Axioms are more like hints to the compiler to speed-up the process of -compilation. -

-

Ignored: Concepts and axioms were removed from the C++11 standard. -

-

Object construction improvement [done]

-

This feature allows classes constructors to call other -constructors with different arguments (similar to Java and C# -behaviour). -

-

The syntax is as follows: -

-
 class SomeType {
-  int number;
- public:
-   SomeType(int newNumber) : number(newNumber) {}
-   SomeType() : SomeType(42) {}
- };

-Also when using the inheritance, the feature introduces inheritance -of all superclass constructors without being defined separately in -the inherited class: -

-
 class BaseClass {
- public:
-   BaseClass(int iValue);
- };
- class DerivedClass: public BaseClass {
-   public:
-   using BaseClass::BaseClass; // Adds DerivedClass(int) constructor
- };

-Swig already correctly parses and produces the correct wrapper for -the “using” keyword.

-

Done: Added testcase cpp11_constructors.i which covers both -constructor delegation and constructor inheritance. R11532

-

Problem: Constructor delegation and constructor inheritance is not -supported by any compiler yet, so it's impossible to try and test -this feature.

-

Null pointer constant [done]

-

nullptr is part of the standard library. -

-

It's defined as typedef decltype(nullptr) nullptr_t; -

-

nullptr_t is defined in <cstddef>. -

-

As far as the C++ is compatible with 0 as the pointer value, swig -values will work for the C++. And the other way around, nullptr -behaves as the ordinary pointer (false, if empty, true, if not -empty), so it's ok for swig to compare it.

-

Done: Written a testcase cpp11_null_pointer_constant.i and -cpp11_null_pointer_constant_runme.py to prove the nullptr -functionality. R11484

-

Strongly typed enumerations [partially done]

-

C++11 introduces a new syntax for strongly typed enum declaration: -

-
 enum class Enumeration {
-  Val1,
-  Val2,
-  Val3 = 100,
-  Val4 /* = 101 */
- };

-Typing if (Val4 == 101) will result in compilation error. -

-

The enum itself can now be explicitely of type int, long, unsigned -int etc.: -

-
 enum class Enum2 : unsigned int {Val1, Val2};

-And it can be forward declared as well: -

-
 enum Enum1;                   //Illegal in C++ and C++11; no size is explicitly specified.
- enum Enum2 : unsigned int;    //Legal in C++11.
- enum class Enum3;             //Legal in C++11, because enum class declarations have a default type of "int".
- enum class Enum4: unsigned int; //Legal C++11.
- enum Enum2 : unsigned short;  //Illegal in C++11, because Enum2 was previously declared with a different type.

-Done: Added syntax 'enum class Name' and forward declarators 'enum -Name : inherited type' or 'enum class Name : inherited type' in -R11449.

-

TODO: Add semantic support for enum elements not clashing with -enum elements in other enum classes. See cpp11_strongly_typed_enums.i -warnings.

-

Problem: Swig currently doesn't support nested classes. This -feature should be implemented using a new nested class when using -“enum class” with a single anonymous “enum {elements}” -element inside. For example:

-
class A { enum class EA { a,b,c,d }; };

-should be mapped to

-
class A { class EA { enum {a,b,c,d}; }; };

-Angle bracket [done]

-

Support for right angled brackets was implemented using the -following article as a base: -http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html -

-

Done: Added support for angle brackets. Used the preferred -"Approach 1". Added a testcase named -cpp11_template_double_brackets. R11245

-

Explicit conversion operators [done]

-

This is used when converting one type to another (eg. if -(myObject) {}, where myObject is your custom class converted to -bool). -

-

Requires both operator and function overloading which is not -supported in any target language (eg. python, php). -

-

Done: Swig already supports the keyword "explicit" for -function types as well. Added test case -cpp11_explicit_conversion_operators. R11323

-

Template typedefs [partially done]

-

The new C++11 will allow creation of wrapper around the template. -For example, if we want to do this:

-
template< typename first, typename second, int third>
-class SomeType;
- 
-template< typename second>
-typedef SomeType<OtherType, second, 5> TypedefName; //Illegal in C++

-This is still illegal! But we can now use the new syntax for -achieving the same effect:

-
template< typename first, typename second, int third>
-class SomeType;
-
-template< typename second>
-using TypedefName = SomeType<OtherType, second, 5>;

-Here we created a new wrapper TypedefName taking one template -argument <second> which creates a type SomeType<OtherType, -second, 5>. OtherType and 5 are predefined here and hidden from -the user – the user only uses TypedefName type.

-

The same goes for the following example:

-
typedef void (*PFD)(double);            // Old style
-using PF = void (*)(double);            // New introduced syntax

-Swig supports parsing typedefs for templates as well for example:

-
typedef List<int> intList;

-Done: Expanded support for the new 'using' syntax and template -aliasing. Added testcase cpp11_template_typedefs. R11533

-

TODO: Make Swig aware of the newly defined typedef. The TYPEDEF -keyword is part of the storage_class rule and type+declarator (see -c_decl rule) is the right part of the definition – for example void -(*PFD)(double) cannot be transformed to void *(double) easily. To -fully support the new 'using' form, we'll probably have to change the -type, type_right rules and declarator, direct_declarator, -notso_direct_declarator etc., which is PITA.

-

Unrestricted unions [done]

-

C++ currently offers usage of unions for types with trivial -constructors only. The new C++11 standard allows usage of types with -non-trivial constructors as well:

-
 struct point {
-  point() {}
-  point(int x, int y): x_(x), y_(y) {}
-  int x_, y_;
- };
- union P {
-  int z;
-  double w;
-  point p;  // Illegal in C++; point has a non-trivial constructor.  However, this is legal in C++11.
- } p1;

-Swig already parses the given syntax.

-

Done: Added testcase cpp11_unrestricted_unions. R11435, R11447

-

Problem: GCC doesn't support unrestricted unions yet so there is -no way to actually test, if it works.

-

Variadic templates [partially done]

-

The new C++11 offers the following syntax:

-
template<typename... Values> class tuple;

-This can be used for example:

-
class tuple<int, std::vector<int>, std::map<std::string, std::vector<int>>> someInstanceName;

-The ... is used in two cases. One is in the template header where it -marks on the left the keywords 'typename' or 'class' and a type name -on the right. The second case is usually in the function block to -decompose typename on the left of the ... . For example:

-
void printf(const char *s) {
-  while (*s) {
-    if (*s == '%' && *(++s) != '%')
-      throw std::runtime_error("invalid format string: missing arguments");
-    std::cout << *s++;
-  }
-}
- 
-template<typename T, typename... Args>
-void printf(const char* s, T value, Args... args) { // recursive action – split previous args to value + args
-  while (*s) {
-    if (*s == '%' && *(++s) != '%') {
-      std::cout << value;
-      printf(*s ? ++s : s, args...); // call even when *s == 0 to detect extra arguments
-      return;
-    }
-    std::cout << *s++;
-  }
-  throw std::logic_error("extra arguments provided to printf");
-}

-The tricky part is that variadic templates can unpack actually -anywhere – including the class inheritance :(

-
template <typename... BaseClasses> class ClassName : public BaseClasses... {
-public:
- 
-   ClassName (BaseClasses&&... baseClasses) : BaseClasses(baseClasses)... {}
-}

-A new extension to sizeof is also introduced with this feature. The -... after sizeof returns number of arguments:

-
template<typename ...Args> struct SomeStruct {
-  static const int size = sizeof...(Args);
-}
-// SomeStruct<Type1, Type2>::size is 2 and SomeStruct<>::size is 0

-Done: Added syntax support for 'typename' or 'class' + ... + id. -Added testcase cpp11_variadic_templates. R11458

-

Done: Added syntax support for BaseClass + ..., type + ... + id in -parameters and baseclass + ... for intializers after constructor. -Extended Swig syntax to support sizeof...(Args). R11467

-

Done: Fixed %template to support variadic number of templates.

-

TODO: Only (if present) first variadically defined argument is -currently used in %template directive. The next ones are ignored.

-

New string literals [partially done]

-

Beside the implementation, the new C++11 Unicode and custom -delimeter constants can occur in templates in the header file. -

-

Done: Added symbols 'u', 'u8' and 'U' to mark the beginning of the -UTF string. Also added test case cpp11_raw_string_literals. R11327

-

Done: Added R"DELIMITER[, ]DELIMITER" for a custom -delimiter for the beginning/end of the string. R11328

-

TODO: Fix the Swig's C++ preprocessor bug when parsing an odd -number of “ inside the string brackets. See -Source/Preprocessor/cpp.c.

-

User-defined literals [partially done]

-

C++ has different suffix literals. eg. 12.5f marks the number 12.5 -as float. -

-

C++11 allows user to define his own suffix for the strings always -starting with the underscore (_). eg. int a = "hello"_mySuffix; -

-

The syntax is similar to other operator overloading functions: -

-
 OutputType operator "" _mySuffix(const char * string_values);

-The null terminated const char* is the string between the "". -The _mySuffix is the name of the suffix operator. And the OutputType -is the outputType the operator returns. -

-

Other forms are: -

-
 OutputType operator "" _mySuffix(const char * string_values, size_t num_chars);
- OutputType operator "" _mySuffix(const wchar_t * string_values, size_t num_chars);
- OutputType operator "" _mySuffix(const char16_t * string_values, size_t num_chars);
- OutputType operator "" _mySuffix(const char32_t * string_values, size_t num_chars);
- OutputType operator "" _mySuffix(int value); /* cooked version - ie. atoi() of string */

-Another possibility is to use variadic templates: -

-
 template<char...> OutputType operator "" _mySuffix();
- OutputType someVariable = "1234"_mySuffix;

-This instantiates the literal processing function as -operator""_Suffix<'1', '2', '3', '4'>. In this form, -there is no terminating null character to the string. The main -purpose to doing this is to use C++11's constexpr keyword and the -compiler to allow the literal to be transformed entirely at compile -time, assuming OutputType is a constexpr-constructable and copyable -type, and the literal processing function is a constexpr function.

-

Article: -http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf

-

Done: Added syntax support for userdefined literals. Added -testcase cpp11_userdefined_literals.i. R11494

-

TODO: %rename doesn't parse operator”” yet.

-

Thread-local storage [done] -

-

New C++11 introduces keyword "thread_local" which marks -the following variable dynamically located depending on the current -thread when using the address-of (&) operator. -

-

Syntax: -

-
 struct A {
-   thread_local int val;
- };

-Done: Add "thread_local" keyword to Swig. Added testcase -cpp11_thread_local. R11393

-

Defaulting/deleting of standard functions on C++ objects [done]

-

C++ automatically creates default constructor with empty -parameters, copy constructor, operator= and destructor for any class. -Sometimes user wants to explicitly remove one of them or enable them -(eg. default constructor with empty parameters doesn't work any more, -if any other constructor is defined). -

-

Words "default" and "delete" are introduced. -The syntax is similar to declaration of pure virtual function: -

-
 struct NonCopyable {
-   NonCopyable & operator=(const NonCopyable&) = delete; /* Removes operator= */
-   NonCopyable(const NonCopyable&) = delete; /* Removed copy constructor */
-   NonCopyable() = default; /* Explicitly allows the empty constructor */
-   void *operator new(std::size_t) = delete; /* Removes new NonCopyable */
- };

-User has the ability by using keyword delete to disallow calling of -the standard functions brought by C++ itself. -

-
 struct A1 {
-   void f(int i);
-   void f(double i) = delete;  /* Don't cast double to int. Compiler returns an error */
- };
- struct A2 {
-   void f(int i);
-   template<class T> void f(T) = delete; /* Only accept int */
- };

-Ignored: Swig already parses the keywords "= delete" and "= -default". These keywords are used for built-in functions (copy -constructor, operator= etc.), which are ignored by Swig anyway.

-

Done: Added testcase cpp11_default_delete. R11535

-

Type long long int [done]

-

Type long long int is an integer type that has at least 64 useful -bits. C99 added it to its standard, but the C++ didn't adopt it until -C++11. Most C++ compilers supported it though. -

-

Done: Swig already parses the C code including the long long type. -

-

Static assertions [done]

-

static_assert() can be used at class scope as well eg.: -

-
 template <typename T>
- struct Check {
-  static_assert(sizeof(int) <= sizeof(T), "not big enough");
- };

-Done: Added syntax support for "static_assert()". Added -test case cpp11_static_assert. R11369

-

Allow sizeof to work on members of classes without an explicit -object [done]

-

C++11 allows calls of sizeof to concrete objects as well: -

-
 struct A { int member; };
- sizeof(A::member); //Does not work with C++03. Okay with C++11

-This kind of syntax is already supported by Swig.

-

Done: Added testcase cpp11_sizeof_objects. R11538 -

-

Threading facilities [ignored]

-

C++11 will add the following classes to the standard library: -

-
 * std::thread
- * std::mutex, std::recursive_mutex
- * std::condition_variable, std::condition_variable_any
- * std::lock_guard, std::unique_lock
- * std::packaged_task

-Ignored: No changes to the language itself is made. -

-

Tuple types [TODO]

-

Tuple is array of various types. C++11 introduced this feature -using variadic templates. Tuple is defined as:

-
template <class ...Types> class tuple;

-Constructor is automatically generated filling the tuple elements. -get<X> function is introduced to get the Xth element in the -tuple.

-
typedef tuple< int, double, long &, const char * > test_tuple ;
-long lengthy = 12 ;
-test_tuple proof( 18, 6.5, lengthy, "Ciao!" ) ;
-lengthy = get<0>(proof) ;  // Assign to 'lengthy' the value 18.
-get<3>(proof) = " Beautiful!" ;  // Modify the tuple’s fourth element.

-Tuples can be copied to each other, if all the elements are copiable:

-
typedef tuple< int , double, string       > tuple_1 t1 ;
-typedef tuple< char, short , const char * > tuple_2 t2( 'X', 2, "Hola!" ) ;
-t1 = t2 ;  // Ok, first two elements can be converted,
-           // the third one can be constructed from a 'const char *'.

-TODO: Implement wrappers for the tuplet<> class.

-

Hash tables [TODO]

-

C++11 introduces the "unordered" version of existing -types, which in practice work faster than the linear types: -

-
 - unordered set
- - unordered multiset
- - unordered map
- - unordered multimap

-Swig should use the "unordered" types exactly the same as -the original linear types.

-

Problem: Unordered types do not contain exactly same members as -ordered ones (eg. _Hashtable_iterator does not offer operator--() and -constructor with compare function which is required). So simply -aliasing unordered classes to ordered ones doesn't work.

-

TODO: Implement wrappers for unordered_ types. Initial work is -already done in Lib/std/unordered_*.i files.

-

Regular expressions [ignored]

-

Two new classes are introduced in C++11: basic_regex and -match_results. Both are defined in regex header file. -

-

Ignored: The new feature extends the standardy library only. No -changes to Swig needed. -

-

General-purpose smart pointers [done]

-

This feature deprecates auto_ptr and adds shared_ptr, weak_ptr and -unique_ptr to the standard library. -

-

This feature only adds the smart pointers to the standard library -and doesn't effect the C++ syntax.

-

Done: Added test case which uses all three smart pointers in the -class. R11394

-

Problem: GCC standard library doesn't contain the new smart -pointers yet. -

-

Extensible random number facility [ignored]

-

This feature standardize the pseudo random number algorithm -(currently, the random number generator was dependent on the -platform/compiler). It adds functions linear_congruential, -subtract_with_carry and mersenne_twister and symbols -uniform_int_distribution, bernoulli_distribution, -geometric_distribution, poisson_distribution, binomial_distribution, -uniform_real_distribution, exponential_distribution, -normal_distribution and gamma_distribution to the standard library. -

-

Ignored: The new feature extends the standardy library only. No -changes to Swig needed. -

-

Wrapper reference [ignored]

-

This feature adds ref and cref classes to the standard library -(#include <utility>) usually used in tempalte functions. -

-

Ignored: The new feature extends the standardy library only. No -changes to Swig needed. -

-

Polymorphous wrappers for function objects [done]

-

Two features are introduced: -

-
    -
  • The function template wrapper: -

    -
-
 function<int ( int, int )> pF;
-
    -
  • and the function object: -

    -
-
 struct Test {
-   bool operator()( short x, short y );
- };

-Swig already supports the two.

-

Done: Added a runtime testcase for function objects -cpp11_function_objects. R11419.

-

Type traits for metaprogramming [ignored]

-

C++11 adds a new header file <type_traits> which includes -helper functions to determine the template type while initializing -the object at compile time. -

-

Swig already supports the following code: -

-
 template< int B, int N >
- struct Pow {
-  // recursive call and recombination.
-  enum{ value = B*Pow< B, N-1 >::value };
- };
- template< int B > struct Pow< B, 0 >  // N == 0 condition of termination.
- {
-  enum{ value = 1 };
- };
- int quartic_of_three = Pow< 3, 4 >::value ;

-Functions is_convertible, is_integral, is_integral_const etc. are -part of the new header: -

-
// First way of operating.
-template< bool B > struct algorithm {
-  template< class T1, class T2 > int do_it( T1 &, T2 & )  { /*...*/ }
-};
-// Second way of operating.
-template<> struct algorithm<true> {
-  template< class T1, class T2 > int do_it( T1, T2 )  { /*...*/ }
-};
-// Instantiating 'elaborate' will automatically instantiate the correct way to operate.
-template< class T1, class T2 > int elaborate( T1 A, T2 B ) {
-  // Use the second way only if 'T1' is an integer and if 'T2' is
-  // in floating point, otherwise use the first way.
-  return algorithm< is_integral<T1>::value && is_floating_point<T2>::value >::do_it( A, B );
-}

-Swig correctly parses the syntax for template<bool>, -template<class T> and template<>. -

-

Ignored: Swig requires explicitly defined template class -(%template directive) to export it to the target language.

-

Uniform method for computing return type of function objects -[partially done]

-

The template function is introduced: std::result_of() which -depends on decltype: -

-
template< class Obj >
-class calculus_ver2 {
- public:
-   template< class Arg >
-   typename std::result_of<Obj(Arg)>::type operator()( Arg& a ) const { 
-     return member(a);
-   }
- private:
-   Obj member;
-};

-Swig correctly parses the result_of class.

-

TODO: The return type (the result_of::type member) is not -calculated by Swig. This needs a much more complex semantic parser.

-

Done: Added testcase cpp11_result_of. R11534

- - diff --git a/Doc/Devel/plan-gsoc-2012.txt b/Doc/Devel/plan-gsoc-2012.txt new file mode 100644 index 000000000..ac764fb2a --- /dev/null +++ b/Doc/Devel/plan-gsoc-2012.txt @@ -0,0 +1,341 @@ + + + + + Project Plan + ============ + SWIG Code Comments + Google Summer of Code 2012 + + +This document describes goals for the Google Summer of Code 2012, +SWIG code documentation project. + +Author: Marko Klopcic, Dmitry Kabak + + +Introduction +============ + +The goal of this project is _not_ to translate _any_ possible Doxygen +formatted comment to JavaDoc or PyDoc, but to make it possible to +translate a subset of comment types in C/C++ code to +JavaDoc and PyDoc. Covering all the Doxygen functionality would be to +complex for the limited time. However, the code must be flexible so +that implementing missing features would not require redesign of the +comment handling code in SWIG. + +There will also be a possibility to add untranslated comments to Java +and Python code (## comments, see Doxygen manual), if the user will +prefer to use Doxygen on the generated code. + +Note: +'-OK-' tick below means that the item is implemented, committed and +working. + +Abbreviations: + JD - JavaDoc + PD - PyDoc + + +Functionality +============= + + Types of comments + ----------------- + + Note: + See 'http://www.stack.nl/~dimitri/doxygen/docblocks.html' for + the detailed description of Doxygen syntax and terms used in this + section. + + 1. -OK- Only JavaDoc (/** */) and Qt (/*! */) styles of comment blocks + will be supported by SWIG translator. + + 2. -OK- The following doc after members will be supported: + + int var; ///< Detailed description after the member + //!< + + int var; //!< Brief description after the member + + int var; ///< Brief description after the member + + + 3. -OK- Only comments before or after declaration/definition will be + supported. Comments with structural commands will be ignored + (warning will be written). (What about writing them to + 'package.info.java' for JD?) + + + Tags + ---- + + This section contains all doxygen tags taken from + http://www.stack.nl/~dimitri/doxygen/commands.html. If a tag is + marked as 'ignored', then the tag is ignored, but the text is copied + to the destination documentation. 'Not implemented' means that the + tag with it's contents is stripped out of the output. + + Doxygen tags: + + All tags: -OK- + + \a - translated to in JD, surrounded with _ in PD + \addindex - ignored + \addtogroup - ignored + \anchor - ignored, not supported by JD and PD + \arg - equivalent to \li + \attention - ignored + \authors, \author - translated to @author in JD, 'Author:' in PD + \b - in JD, surrounded with __ in PD + \brief - ignored + \bug - ignored + \c - translated to in JD, ignored in PD + \callgraph - ignored, not supported by JD and PD + \callergraph - ignored, not supported by JD and PD + \category - ignored, used only in Objective C + \cite - translated to in JD, single quotes in PD + \class - ignored (structural command) + \code - translated to {@code ...} in JD, ignored in PD + \cond - translated to 'Conditional comment: '. Later + SWIG may support definitions of conditions in config file. + \copybrief - ignored. Later SWIG may support this command by + performing copy + \copydetails - ignored. Later SWIG may support this command by + performing copy + \copydoc - ignored. Later SWIG may support this command by + performing copy + \copyright - replaced with text 'Copyright' in PD and PD + \date - ignored + \def - ignored (structural command) + \defgroup - not supported + \deprecated - translated to @deprecated in JD, 'Deprecated:' in PD + \details - ignored + \dir - not supported + \dontinclude - not supported + \dot - not supported. Later SWIG may call dot and produce the graph image + to include in JD and PD + \dotfile - see note for \dot + \e - equivalent \a + \else - see note for \cond + \elseif - see note for \cond + \em - equivalent to \a + \endcode - see note for \code + \endcond - translated to 'End of conditional comment: '. Later + SWIG may support definitions of conditions in config file. + \enddot - see note for \dot + \endhtmlonly - ignored + \endif - see note for \cond + \endinternal - ignored + \endlatexonly - ignored + \endlink - see note for \link + \endmanonly - ignored + \endmsc - see note for \msc + \endrtfonly - ignored + \endverbatim - see note for \verbatim + \endxmlonly - ignored + \enum - ignored (structural command) + \example - translated to 'Example:' in JD and PD + \exception - equivalent to throws, but translates to @exception in JD + \extends - not supported + \f$ - ignored. Later swig may call LATeX to produce bitmaps with formulas + to include in JD and PD + \f[ - see note for \f$ + \f] - see note for \f$ + \f{ - see note for \f$ + \f} - see note for \f$ + \file - ignored (structural command) + \fn - ignored (structural command) + \headerfile - not supported + \hideinitializer - not supported + \htmlinclude - not supported + \htmlonly - ignored + \if - see note for \cond + \ifnot - see note for \cond + \image - translated to in JD only when target=HTML, translated to + 'Image: filename(Title)' + \implements - not supported + \include - not supported + \includelineno - not supported + \ingroup - not supported. Later swig may print group names as plain text + in comments like 'Code group: something' in both JD and PD + \internal - ignored + \invariant - ignored + \interface - ignored (structural command) + \latexonly - ignored + \li - trabslated to
  • in JD, ignored in PD + \line - not supported + \link - translated to {@link ...} in JD, ignored in PD + \mainpage - ignored + \manonly - ignored + \memberof - not supported + \msc - not supported. Later SWIG may call dot and produce the graph image + to include in JD and PD + \mscfile - see note for \msc + \n - prints the new line + \name - ignored + \namespace - included in package-info.java if nspace feature is enabled, + otherwise ignored, ignored in PD + \nosubgrouping - ignored + \note - translated to 'Note:' in both JD and PD + \overload - prints 'This is an overloaded member function, provided for + convenience. It differs from the above function only in what + argument(s) it accepts.' to the output in both JD and PD + \p - equivalent to \c + \package - is kept same in JD (it is already a JD tag), ignored in PD + \page - ignored + \par - translated to

    in JD, 'Title: ...' in PD + \paragraph - ignored + \param - translated to @param in JD, special formatting in PD + \post - ignored + \pre - ignored + \private - ignored + \privatesection - ignored + \property - ignored + \protected - ignored + \protectedsection - ignored + \protocol - ignored (Objective-C tag) + \public - ignored + \publicsection - ignored + \ref - ignored, not supported by JD and PD + \related - ignored + \relates - ignored + \relatedalso - ignored + \relatesalso - ignored + \remark - translated to 'Remarks:' in both JD and PD + \remarks - equivalent to remark + \result - translated to @return in JD, 'Return:' in PD + \return - equivalent to result + \returns - equivalent to result + \retval - ignored + \rtfonly - ignored + \sa - translated to @see in JD, 'See also:' in PD + \section - not supported + \see - equivalent to \sa + \short - equivalent to \brief + \showinitializer - not supported + \since - translated to @since in JD, 'Since:' in PD + \skip - not supported + \skipline - not supported + \snippet - not supported + \struct - ignored (structural command) + \subpage - not supported + \subsection - not supported + \subsubsection - not supported + \tableofcontents - not supported + \test - ignored + \throw - translated to @throws in JD, 'Throws:' in PD + \throws - equivalent to \throw + \todo - translated to 'TODO:' in both JD and PD + \tparam - similar to \arg + \typedef - ignored (structural command) + \union - ignored (structural command) + \until - not supported + \var - ignored (structural command) + \verbatim - translated to {@literal ...} in JD, ignored in PD + \verbinclude - ignored + \version - translated to @version in JD, 'Version:' in PD + \warning - translated to 'Warning:' in both JD and PD + \weakgroup - not supported + \xmlonly - ignored + \xrefitem - ignored + \$ - this and all the others below: these commands insert single char, + it is escaped as HTML char in JD, kept as-is in PD + \@ + \\ + \& + \~ + \< + \> + \# + \% + \" + \. + \:: + +Optional functionality +====================== + +That section describes some complex cases where the current code +does not behave really well. Like a short to-do list of special cases. + +-OK- When translating functions with default parameters in swig to +java, it creates overloaded functions with all the parameters +except the default ones. We need to copy the doxygen comment to +such functions and correct the list of @param tags. + +-OK- In doxygen there is a special tags (and even a special option) +to create links to some code members from the current comment. +Sometimes it needs a type of parameters specified because of the +overloaded functions. And the same linking tags are supported in JD, +but it has a completely different typesystem, so we need to translate +the types of function parameters in comments also. For example: +{@link MyClass#doSomething(const std::string &)} +does not make sense in Java, so the type should be converted. +{@link MyClass#doSomething(String)} + + +Tests +===== + +The following test cases will be implemented: + +-OK- Class comments. + +-OK- Struct comments. +-OK- Enum comments. +-OK- Function comments. +-OK- Var comments. + +-OK- Class attributes, comment before and after declaration. +-OK- Class methods, comment of parameters in function + comment. +-OK- Class methods, comment of parameters + after parameter declaration. + +-OK- Struct attributes, comment before and after declaration. +-OK- Struct methods, comment of parameters in function + comment. +-OK- Struct methods, comment of parameters + after parameter declaration. + +-OK- Enum items JD and Qt style, comment before items +-OK- Enum items JD and Qt style, comment after items + +-OK- Class comment, with all supported tags. +-OK- Class comment, with all doxygen tags, including + ignored ones. + +The list of all tests, in form of shell commands to make it simple +to test project by copying the text below into terminal program. +make doxygen_parsing.cpptest -s +make doxygen_translate.cpptest -s +make doxygen_translate_all_tags.cpptest -s +make doxygen_basic_translate.cpptest -s +make doxygen_basic_notranslate.cpptest -s +make doxygen_translate_links.cpptest -s +make doxygen_tricky_constructs.cpptest -s + + +Refactoring +=========== + +All the code in directory _Doxygen_ should be refactored: +-OK- all methods should be class members +-OK- most static methods should be normal members +-OK- replace C arrays of strings and sequential searches with STL data + structures and algorithms. +-OK- use singletons instead of class instantiaion for each comment found. + + +Documentation +============= + +SWIG documentation will contain: +-OK- command line options +-OK- list of implemented features (types and placements of comments) +-OK- list of unimplemented features (types and placements of comments) +-OK- list of tags and their translations (all Doxygen tags). +-OK- some amount of debugging and development information + diff --git a/Doc/Devel/runtime.txt b/Doc/Devel/runtime.txt index f88edf767..ae9c83275 100644 --- a/Doc/Devel/runtime.txt +++ b/Doc/Devel/runtime.txt @@ -57,7 +57,7 @@ Alternatively, if the language supports modules, a module named named "type_table" SWIG_TYPE_TABLE_NAME can be created inside it. The most common approach is to store the mod pointer in some global variable in the target language, but if the language provides an alternative place to store data -(like the chicken module), then that is good too. +then that is good too. The way the code is set up, SetModule should only be called when GetModule returns NULL, and if SetModule is called a second time, the behavior is @@ -105,7 +105,7 @@ Standard Functions These functions are not required and their API is not formalized, but almost all language modules implement them for consistency across languages. Throughout this discussion, I will use LangType to represent the underlying language type -(C_word in chicken, Scheme_Object * in mzscheme, PyObject * in python, etc) +(Scheme_Object * in mzscheme, PyObject * in python, etc) diff --git a/Doc/Devel/tree.html b/Doc/Devel/tree.html index 73a49ed55..5bb4b6a1e 100644 --- a/Doc/Devel/tree.html +++ b/Doc/Devel/tree.html @@ -236,7 +236,7 @@ The following functions can be used to help debug SWIG parse trees.
    Prints the tag-structure of the parse tree to standard output. node is the top-level parse tree node. prefix is -a string prefix thats added to the start of each line. Normally, you would specify the empty string or NIL for prefix. +a string prefix that's added to the start of each line. Normally, you would specify the empty string or NIL for prefix. This function is called by the -debug-tags option to SWIG.
    diff --git a/Doc/Manual/Allegrocl.html b/Doc/Manual/Allegrocl.html
    index 4b6bad421..4069ecd8b 100644
    --- a/Doc/Manual/Allegrocl.html
    +++ b/Doc/Manual/Allegrocl.html
    @@ -8,7 +8,7 @@
     
     
     
    -

    18 SWIG and Allegro Common Lisp

    +

    20 SWIG and Allegro Common Lisp

      @@ -129,16 +129,16 @@ It is significant to note that, while this is a vendor-specific module, we would like to acknowledge the current and ongoing work by developers in the open source lisp community that are working on similar interfaces to implementation-independent -foreign function interfaces (UFFI or CFFI, for example). Such +foreign function interfaces (CFFI, for example). Such work can only benefit the lisp community, and we would not be unhappy to see some enterprising folk use this work to add to it.

      -

      18.1 Basics

      +

      20.1 Basics

      -

      18.1.1 Running SWIG

      +

      20.1.1 Running SWIG

      @@ -155,7 +155,7 @@ SWIG directives. SWIG can be furnished with a header file, but an interface can also be generated without library headers by supplying a simple text file--called the interface file, which is typically named with a .i extension--containing any foreign declarations of -identifiers you wish to use. The most common approach is to use a an +identifiers you wish to use. The most common approach is to use an interface file with directives to parse the needed headers. A straight parse of library headers will result in usable code, but SWIG directives provides much freedom in how a user might tailor the @@ -280,39 +280,39 @@ actual function.

      example_wrap.i
      -   ... lots of SWIG internals ...
      +  ... lots of SWIG internals ...
       
       EXPORT int ACL___fact__SWIG_0 (char *larg1) {
      -    int lresult = (int)0 ;
      -    char *arg1 = (char *) 0 ;
      -    int result;
      -    
      -    arg1 = larg1;
      -    try {
      -        result = (int)fact(arg1);
      -        
      -        lresult = result;
      -        return lresult;
      -    } catch (...) {
      -        return (int)0;
      -    }
      +  int lresult = (int)0 ;
      +  char *arg1 = (char *) 0 ;
      +  int result;
      +
      +  arg1 = larg1;
      +  try {
      +    result = (int)fact(arg1);
      +
      +    lresult = result;
      +    return lresult;
      +  } catch (...) {
      +    return (int)0;
      +  }
       }
       
       
       EXPORT int ACL___fact__SWIG_1 (int larg1) {
      -    int lresult = (int)0 ;
      -    int arg1 ;
      -    int result;
      -    
      -    arg1 = larg1;
      -    try {
      -        result = (int)fact(arg1);
      -        
      -        lresult = result;
      -        return lresult;
      -    } catch (...) {
      -        return (int)0;
      -    }
      +  int lresult = (int)0 ;
      +  int arg1 ;
      +  int result;
      +
      +  arg1 = larg1;
      +  try {
      +    result = (int)fact(arg1);
      +
      +    lresult = result;
      +    return lresult;
      +  } catch (...) {
      +    return (int)0;
      +  }
       }
       
      @@ -324,7 +324,7 @@ what is generated when parsing C code:
      -   ...
      +  ...
       
       (swig-in-package ())
       
      @@ -360,7 +360,7 @@ need to link in the Allegro shared library. The library you create from
       the C++ wrapper will be what you then load into Allegro CL.
       

      -

      18.1.2 Command Line Options

      +

      20.1.2 Command Line Options

      @@ -396,7 +396,7 @@ See Section 17.5 Identifier converter functions for more details.

      -

      18.1.3 Inserting user code into generated files

      +

      20.1.3 Inserting user code into generated files

      @@ -436,7 +436,7 @@ Note that the block %{ ... %} is effectively a shortcut for

      -

      18.2 Wrapping Overview

      +

      20.2 Wrapping Overview

      @@ -446,7 +446,7 @@ New users to SWIG are encouraged to read interested in generating an interface to C++.

      -

      18.2.1 Function Wrapping

      +

      20.2.1 Function Wrapping

      @@ -499,7 +499,7 @@ interested in generating an interface to C++.

      -

      18.2.2 Foreign Wrappers

      +

      20.2.2 Foreign Wrappers

      @@ -512,7 +512,7 @@ interested in generating an interface to C++. typemap.

      -

      18.2.3 FFI Wrappers

      +

      20.2.3 FFI Wrappers

      @@ -526,8 +526,8 @@ interested in generating an interface to C++.

       %module ffargs
       
      -%ffargs(strings_convert="nil",call_direct="t") foo;
      -%ffargs(strings_convert="nil",release_heap=":never",optimize_for_space="t") bar;
      +%ffargs(strings_convert="nil", call_direct="t") foo;
      +%ffargs(strings_convert="nil", release_heap=":never", optimize_for_space="t") bar;
       
       int foo(float f1, float f2);
       int foo(float f1, char c2);
      @@ -593,7 +593,7 @@ char *xxx();
           ff:def-foreign-call's.
         

      -

      18.2.4 Non-overloaded Defuns

      +

      20.2.4 Non-overloaded Defuns

      @@ -606,11 +606,11 @@ char *xxx(); this function can be manipulated via the lout typemap.

      -

      18.2.5 Overloaded Defuns

      +

      20.2.5 Overloaded Defuns

      - In the case of overloaded functions, mulitple layers are + In the case of overloaded functions, multiple layers are generated. First, all the overloads for a given name are separated out into groups based on arity, and are wrapped in defmethods. Each method calls a distinct wrapper function, but are @@ -622,7 +622,7 @@ char *xxx(); can be manipulated via the lout typemap.

      -

      18.2.6 What about constant and variable access?

      +

      20.2.6 What about constant and variable access?

      @@ -635,7 +635,7 @@ char *xxx(); into the foreign module.

      -

      18.2.7 Object Wrapping

      +

      20.2.7 Object Wrapping

      @@ -657,7 +657,7 @@ char *xxx(); foreign function interface.

      -

      18.3 Wrapping Details

      +

      20.3 Wrapping Details

      @@ -665,7 +665,7 @@ char *xxx(); translated into lisp.

      -

      18.3.1 Namespaces

      +

      20.3.1 Namespaces

      @@ -688,10 +688,10 @@ char *xxx(); %include "foo.h" namespace car { - ... - namespace tires { - int do_something(int n); - } + ... + namespace tires { + int do_something(int n); + } }

    @@ -742,7 +742,7 @@ namespace car { function such as (car '(1 2 3).

    -

    18.3.2 Constants

    +

    20.3.2 Constants

    @@ -803,7 +803,7 @@ namespace car { not use the -nocwrap command-line option.

    -

    18.3.3 Variables

    +

    20.3.3 Variables

    @@ -881,7 +881,7 @@ globalvar> (globalvar.nnn::glob_float)

    -

    18.3.4 Enumerations

    +

    20.3.4 Enumerations

    @@ -957,7 +957,7 @@ EXPORT const int ACL_ENUM___FOO3__SWIG_0 = FOO3; -

    18.3.5 Arrays

    +

    20.3.5 Arrays

    @@ -1105,10 +1105,10 @@ namespace BAR { -

    18.3.6 Classes and Structs and Unions (oh my!)

    +

    20.3.6 Classes and Structs and Unions (oh my!)

    -

    18.3.6.1 CLOS wrapping of

    +

    20.3.6.1 CLOS wrapping of

    @@ -1123,7 +1123,7 @@ namespace BAR { integer values.

    -

    18.3.6.2 CLOS Inheritance

    +

    20.3.6.2 CLOS Inheritance

    @@ -1136,7 +1136,7 @@ namespace BAR { parameter.

    -

    18.3.6.3 Member fields and functions

    +

    20.3.6.3 Member fields and functions

    @@ -1152,7 +1152,7 @@ namespace BAR { the interface does nothing for friend directives,

    -

    18.3.6.4 Why not directly access C++ classes using foreign types?

    +

    20.3.6.4 Why not directly access C++ classes using foreign types?

    @@ -1170,11 +1170,11 @@ namespace BAR { use the more robust wrapper functions.

    -

    18.3.7 Templates

    +

    20.3.7 Templates

    -

    18.3.7.1 Generating wrapper code for templates

    +

    20.3.7.1 Generating wrapper code for templates

    @@ -1187,7 +1187,7 @@ them. This is done via the directive.

    -

    18.3.7.2 Implicit Template instantiation

    +

    20.3.7.2 Implicit Template instantiation

    @@ -1197,7 +1197,7 @@ to include these templated classes in the foreign-type and CLOS class schema.

    -

    18.3.8 Typedef, Templates, and Synonym Types

    +

    20.3.8 Typedef, Templates, and Synonym Types

    @@ -1209,8 +1209,8 @@ class schema.

    synonyms.h
     class A { 
    -   int x;
    -   int y;
    +  int x;
    +  int y;
     };
     
     typedef A Foo;
    @@ -1239,7 +1239,7 @@ int zzz(A *inst = 0);  /* return inst->x + inst->y */
           We resolve this issue, by noting synonym relationships between
           types while generating the interface. A Primary type is selected
           (more on this below) from the candidate list of synonyms. For
    -      all other synonyms, intead of generating a distinct CLOS class
    +      all other synonyms, instead of generating a distinct CLOS class
           definition, we generate a form that expands to:
         

    @@ -1277,7 +1277,7 @@ synonym>
    -

    18.3.8.1 Choosing a primary type

    +

    20.3.8.1 Choosing a primary type

    @@ -1298,7 +1298,7 @@ synonym> -

    18.3.9 Function overloading/Parameter defaulting

    +

    20.3.9 Function overloading/Parameter defaulting

    @@ -1336,70 +1336,70 @@ float xxx(A *inst, int x); /* return x + A->x + A->y */

    overload_wrap.cxx
     EXPORT void ACL___delete_A__SWIG_0 (A *larg1) {
    -    A *arg1 = (A *) 0 ;
    -    
    -    arg1 = larg1;
    -    try {
    -        delete arg1;
    -        
    -    } catch (...) {
    -        
    -    }
    +  A *arg1 = (A *) 0 ;
    +
    +  arg1 = larg1;
    +  try {
    +    delete arg1;
    +
    +  } catch (...) {
    +
    +  }
     }
     
     
     EXPORT float ACL___xxx__SWIG_0 (int larg1, int larg2) {
    -    float lresult = (float)0 ;
    -    int arg1 ;
    -    int arg2 ;
    -    float result;
    -    
    -    arg1 = larg1;
    -    arg2 = larg2;
    -    try {
    -        result = (float)xxx(arg1,arg2);
    -        
    -        lresult = result;
    -        return lresult;
    -    } catch (...) {
    -        return (float)0;
    -    }
    +  float lresult = (float)0 ;
    +  int arg1 ;
    +  int arg2 ;
    +  float result;
    +
    +  arg1 = larg1;
    +  arg2 = larg2;
    +  try {
    +    result = (float)xxx(arg1, arg2);
    +
    +    lresult = result;
    +    return lresult;
    +  } catch (...) {
    +    return (float)0;
    +  }
     }
     
     
     EXPORT float ACL___xxx__SWIG_1 (int larg1) {
    -    float lresult = (float)0 ;
    -    int arg1 ;
    -    float result;
    -    
    -    arg1 = larg1;
    -    try {
    -        result = (float)xxx(arg1);
    -        
    -        lresult = result;
    -        return lresult;
    -    } catch (...) {
    -        return (float)0;
    -    }
    +  float lresult = (float)0 ;
    +  int arg1 ;
    +  float result;
    +
    +  arg1 = larg1;
    +  try {
    +    result = (float)xxx(arg1);
    +
    +    lresult = result;
    +    return lresult;
    +  } catch (...) {
    +    return (float)0;
    +  }
     }
     
     
     EXPORT float ACL___xxx__SWIG_2 (A *larg1, int larg2) {
    -    float lresult = (float)0 ;
    -    A *arg1 = (A *) 0 ;
    -    int arg2 ;
    -    float result;
    -    
    -    arg1 = larg1;
    -    arg2 = larg2;
    -    try {
    -        result = (float)xxx(arg1,arg2);
    -        
    -        lresult = result;
    -        return lresult;
    -    } catch (...) {
    -        return (float)0;
    -    }
    +  float lresult = (float)0 ;
    +  A *arg1 = (A *) 0 ;
    +  int arg2 ;
    +  float result;
    +
    +  arg1 = larg1;
    +  arg2 = larg2;
    +  try {
    +    result = (float)xxx(arg1, arg2);
    +
    +    lresult = result;
    +    return lresult;
    +  } catch (...) {
    +    return (float)0;
    +  }
     }
         
    @@ -1461,7 +1461,7 @@ overload> -

    18.3.10 Operator wrapping and Operator overloading

    +

    20.3.10 Operator wrapping and Operator overloading

    @@ -1607,7 +1607,7 @@ opoverload> -

    18.3.11 Varargs

    +

    20.3.11 Varargs

    @@ -1628,7 +1628,7 @@ opoverload> with other ways such functions can be wrapped.

    -

    18.3.12 C++ Exceptions

    +

    20.3.12 C++ Exceptions

    @@ -1640,7 +1640,7 @@ opoverload> implemented.

    -

    18.3.13 Pass by value, pass by reference

    +

    20.3.13 Pass by value, pass by reference

    @@ -1652,7 +1652,7 @@ opoverload> newly defined types.

    -

    18.4 Typemaps

    +

    20.4 Typemaps

    @@ -1663,7 +1663,7 @@ opoverload> on Typemaps for more information.

    -

    18.4.1 Code Generation in the C++ Wrapper

    +

    20.4.1 Code Generation in the C++ Wrapper

    @@ -1675,25 +1675,25 @@ opoverload>
     return-val wrapper-name(parm0, parm1, ..., parmN)
     {
    -   return-val lresult;   /* return value from wrapper */
    -   <local-declaration>
    -   ... results;          /* return value from function call */
    +  return-val lresult;   /* return value from wrapper */
    +  <local-declaration>
    +  ... results;          /* return value from function call */
     
    -   <binding locals to parameters>
    +  <binding locals to parameters>
     
    -   try {
    -      result = function-name(local0, local1, ..., localN);
    +  try {
    +    result = function-name(local0, local1, ..., localN);
     
    -      <convert and bind result to lresult>
    +    <convert and bind result to lresult>
     
    -      return lresult;
    -   catch (...) {
    -      return (int)0;
    -   }
    +    return lresult;
    +  catch (...) {
    +    return (int)0;
    +  }
         
    -

    18.4.1.1 IN Typemap

    +

    20.4.1.1 IN Typemap

    @@ -1728,7 +1728,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) -

    18.4.1.2 OUT Typemap

    +

    20.4.1.2 OUT Typemap

    @@ -1752,7 +1752,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) -

    18.4.1.3 CTYPE Typemap

    +

    20.4.1.3 CTYPE Typemap

    @@ -1784,7 +1784,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) these common typemaps here.

    -

    18.4.2 Code generation in Lisp wrappers

    +

    20.4.2 Code generation in Lisp wrappers

    @@ -1803,7 +1803,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) 16.3.1 Namespaces for details.

    -

    18.4.2.1 LIN Typemap

    +

    20.4.2.1 LIN Typemap

    @@ -1846,7 +1846,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) -

    18.4.2.2 LOUT Typemap

    +

    20.4.2.2 LOUT Typemap

    @@ -1889,7 +1889,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) -

    18.4.2.3 FFITYPE Typemap

    +

    20.4.2.3 FFITYPE Typemap

    @@ -1939,7 +1939,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) -

    18.4.2.4 LISPTYPE Typemap

    +

    20.4.2.4 LISPTYPE Typemap

    @@ -1959,7 +1959,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) -

    18.4.2.5 LISPCLASS Typemap

    +

    20.4.2.5 LISPCLASS Typemap

    @@ -1983,7 +1983,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) -

    18.4.3 Modifying SWIG behavior using typemaps

    +

    20.4.3 Modifying SWIG behavior using typemaps

    @@ -2017,10 +2017,10 @@ return-val wrapper-name(parm0, parm1, ..., parmN) -

    18.5 Identifier Converter functions

    +

    20.5 Identifier Converter functions

    -

    18.5.1 Creating symbols in the lisp environment

    +

    20.5.1 Creating symbols in the lisp environment

    @@ -2041,11 +2041,11 @@ return-val wrapper-name(parm0, parm1, ..., parmN) of arguments.

    -

    18.5.2 Existing identifier-converter functions

    +

    20.5.2 Existing identifier-converter functions

    Two basic identifier routines have been defined. -

    18.5.2.1 identifier-convert-null

    +

    20.5.2.1 identifier-convert-null

    @@ -2054,7 +2054,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) strings, from which a symbol will be created.

    -

    18.5.2.2 identifier-convert-lispify

    +

    20.5.2.2 identifier-convert-lispify

    @@ -2063,7 +2063,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) same symbol transformations.

    -

    18.5.2.3 Default identifier to symbol conversions

    +

    20.5.2.3 Default identifier to symbol conversions

    @@ -2072,7 +2072,7 @@ return-val wrapper-name(parm0, parm1, ..., parmN) default naming conventions.

    -

    18.5.3 Defining your own identifier-converter

    +

    20.5.3 Defining your own identifier-converter

    @@ -2128,7 +2128,7 @@ indicating the number of arguments passed to the routine indicated by this identifier.

    -

    18.5.4 Instructing SWIG to use a particular identifier-converter

    +

    20.5.4 Instructing SWIG to use a particular identifier-converter

    diff --git a/Doc/Manual/Android.html b/Doc/Manual/Android.html index 8838e67a9..944a88d65 100644 --- a/Doc/Manual/Android.html +++ b/Doc/Manual/Android.html @@ -6,7 +6,7 @@ -

    19 SWIG and Android

    +

    21 SWIG and Android

      @@ -31,7 +31,7 @@ This chapter describes SWIG's support of Android. -

      19.1 Overview

      +

      21.1 Overview

      @@ -41,14 +41,14 @@ Everything in the Java chapter applies to generatin This chapter contains a few Android specific notes and examples.

      -

      19.2 Android examples

      +

      21.2 Android examples

      -

      19.2.1 Examples introduction

      +

      21.2.1 Examples introduction

      -The examples require the Android SDK and Android NDK which can be installed as per instructions in the links. +The examples require the Android SDK and Android NDK which can be installed as per instructions in the links. The Eclipse version is not required for these examples as just the command line tools are used (shown for Linux as the host, but Windows will be very similar, if not identical in most places). Add the SDK tools and NDK tools to your path and create a directory somewhere for your Android projects (adjust PATH as necessary to where you installed the tools):

      @@ -77,7 +77,7 @@ $ android list targets The following examples are shipped with SWIG under the Examples/android directory and include a Makefile to build and install each example.

      -

      19.2.2 Simple C example

      +

      21.2.2 Simple C example

      @@ -326,7 +326,7 @@ include $(BUILD_SHARED_LIBRARY)

    -See the Android NDK documentation for more on the NDK build system and getting started with the NDK. +See the Android NDK documentation for more on the NDK build system and getting started with the NDK. A simple invocation of ndk-build will compile the .c files and generate a shared object/system library. Output will be similar to:

    @@ -354,7 +354,7 @@ Modify the nativeCall method in src/org/swig/simple/SwigSimple.java int x = 42; int y = 105; - int g = example.gcd(x,y); + int g = example.gcd(x, y); outputText.append("The greatest common divisor of " + x + " and " + y + " is " + g + "\n"); // Manipulate the Foo global variable @@ -399,7 +399,7 @@ Run the app again and this time you will see the output pictured below, showing
    Android screenshot of SwigSimple example
    -

    19.2.3 C++ class example

    +

    21.2.3 C++ class example

    @@ -409,7 +409,7 @@ All the steps required to compile and use a simple hierarchy of classes for shap

    First create an Android project called SwigClass in a subdirectory called class. -The steps below create and build a the JNI C++ app. +The steps below create and build the JNI C++ app. Adjust the --target id as mentioned earlier in the Examples introduction.

    @@ -661,7 +661,7 @@ public class SwigClass extends Activity // ----- Call some methods ----- outputText.append( "\nHere are some properties of the shapes:\n" ); - Shape[] shapes = {c,s}; + Shape[] shapes = {c, s}; for (int i=0; i<shapes.length; i++) { outputText.append( " " + shapes[i].toString() + "\n" ); @@ -747,7 +747,7 @@ Run the app to see the result of calling the C++ code from Java:
    Android screenshot of SwigClass example
    -

    19.2.4 Other examples

    +

    21.2.4 Other examples

    @@ -759,7 +759,7 @@ Note that the 'extend' example is demonstrates the directors feature. Normally C++ exception handling and the STL is not available by default in the version of g++ shipped with Android, but this example turns these features on as described in the next section.

    -

    19.3 C++ STL

    +

    21.3 C++ STL

    diff --git a/Doc/Manual/Arguments.html b/Doc/Manual/Arguments.html index 48ec5c629..2828bf4df 100644 --- a/Doc/Manual/Arguments.html +++ b/Doc/Manual/Arguments.html @@ -7,7 +7,7 @@ -

    10 Argument Handling

    +

    12 Argument Handling

      @@ -32,7 +32,7 @@

      -In Chapter 3, SWIG's treatment of basic datatypes and pointers was +In Chapter 5, SWIG's treatment of basic datatypes and pointers was described. In particular, primitive types such as int and double are mapped to corresponding types in the target language. For everything else, pointers are used to refer to @@ -43,7 +43,7 @@ return multiple values through the arguments of a function. This chapter describes some of the techniques for doing this.

      -

      10.1 The typemaps.i library

      +

      12.1 The typemaps.i library

      @@ -51,7 +51,7 @@ This section describes the typemaps.i library file--commonly used to change certain properties of argument conversion.

      -

      10.1.1 Introduction

      +

      12.1.1 Introduction

      @@ -100,7 +100,7 @@ like this (shown for Python):

      ->>> a = add(3,4)
      +>>> a = add(3, 4)
       >>> print a
       7
       >>>
      @@ -148,7 +148,7 @@ For example, consider this code:
       %include "typemaps.i"
       %apply int *OUTPUT { int *width, int *height };
       
      -// Returns a pair (width,height)
      +// Returns a pair (width, height)
       void getwinsize(int winid, int *width, int *height);
       
      @@ -158,7 +158,7 @@ In this case, the function returns multiple values, allowing it to be used like

      ->>> w,h = genwinsize(wid)
      +>>> w, h = genwinsize(wid)
       >>> print w
       400
       >>> print h
      @@ -195,7 +195,7 @@ else.   To clear a typemap, the %clear directive should be used.  For e
       
      -

      10.1.2 Input parameters

      +

      12.1.2 Input parameters

      @@ -245,10 +245,10 @@ When the function is used in the scripting language interpreter, it will work li

      -result = add(3,4)
      +result = add(3, 4)
       
      -

      10.1.3 Output parameters

      +

      12.1.3 Output parameters

      @@ -315,7 +315,7 @@ iresult, dresult = foo(3.5, 2)

    -

    10.1.4 Input/Output parameters

    +

    12.1.4 Input/Output parameters

    @@ -380,7 +380,7 @@ rather than directly overwriting the value of the original input object. SWIG. Backwards compatibility is preserved, but deprecated.

    -

    10.1.5 Using different names

    +

    12.1.5 Using different names

    @@ -414,7 +414,7 @@ Typemap declarations are lexically scoped so a typemap takes effect from the poi file or a matching %clear declaration.

    -

    10.2 Applying constraints to input values

    +

    12.2 Applying constraints to input values

    @@ -424,7 +424,7 @@ insure that a value is positive, or that a pointer is non-NULL. This can be accomplished including the constraints.i library file.

    -

    10.2.1 Simple constraint example

    +

    12.2.1 Simple constraint example

    @@ -450,7 +450,7 @@ the arguments violate the constraint condition, a scripting language exception will be raised. As a result, it is possible to catch bad values, prevent mysterious program crashes and so on.

    -

    10.2.2 Constraint methods

    +

    12.2.2 Constraint methods

    @@ -466,7 +466,7 @@ NONNULL Non-NULL pointer (pointers only). -

    10.2.3 Applying constraints to new datatypes

    +

    12.2.3 Applying constraints to new datatypes

    diff --git a/Doc/Manual/CCache.html b/Doc/Manual/CCache.html index d23b0cb2f..edd435fa1 100644 --- a/Doc/Manual/CCache.html +++ b/Doc/Manual/CCache.html @@ -7,7 +7,7 @@ -

    17 Using SWIG with ccache - ccache-swig(1) manpage

    +

    20 Using SWIG with ccache - ccache-swig(1) manpage

    -

    17.14 HISTORY

    +

    20.14 HISTORY

    -ccache was inspired by the compilercache shell script script written +ccache was inspired by the compilercache shell script written by Erik Thiele and I would like to thank him for an excellent piece of work. See http://www.erikyyy.de/compilercache/ @@ -423,7 +423,7 @@ I wrote ccache because I wanted to get a bit more speed out of a compiler cache and I wanted to remove some of the limitations of the shell-script version.

    -

    17.15 DIFFERENCES FROM COMPILERCACHE

    +

    20.15 DIFFERENCES FROM COMPILERCACHE

    @@ -441,7 +441,7 @@ are:

  • ccache avoids a double call to cpp on a cache miss

    -

    17.16 CREDITS

    +

    20.16 CREDITS

    @@ -453,12 +453,12 @@ Thanks to the following people for their contributions to ccache

  • Paul Russell for many suggestions and the debian packaging

    -

    17.17 AUTHOR

    +

    20.17 AUTHOR

    ccache was written by Andrew Tridgell -http://samba.org/~tridge/. +https://www.samba.org/~tridge/. ccache was adapted to create ccache-swig for use with SWIG by William Fulton.

    If you wish to report a problem or make a suggestion then please email diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index c825d8426..11335a251 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -32,6 +32,7 @@

  • Type alias and alias templates
  • Unrestricted unions
  • Variadic templates +
  • New character literals
  • New string literals
  • User-defined literals
  • Thread-local storage @@ -42,6 +43,7 @@
  • Exception specifications and noexcept
  • Control and query object alignment
  • Attributes +
  • Methods with ref-qualifiers
  • Standard library changes
      @@ -203,7 +205,7 @@ public:

      And then call this constructor from your target language, for example, in Python, the following will call the constructor taking the std::vector:

      ->>> c = Container( [1,2,3,4] )
      +>>> c = Container( [1, 2, 3, 4] )
       

      @@ -392,7 +394,7 @@ auto SomeStruct::FuncName(int x, int y) -> int {

       >>> a = SomeStruct()
      ->>> a.FuncName(10,5)
      +>>> a.FuncName(10, 5)
       15
       
      @@ -457,10 +459,10 @@ This kind of initialization is handled by SWIG.
       class SomeClass {
       public:
      -    SomeClass() {}
      -    explicit SomeClass(int new_value) : value(new_value) {}
      +  SomeClass() {}
      +  explicit SomeClass(int new_value) : value(new_value) {}
       
      -    int value = 5;
      +  int value = 5;
       };
       
      @@ -622,20 +624,15 @@ which is equivalent to the old style typedef: typedef void (*PFD)(double); // The old style
  • -

    -SWIG supports type aliasing. -

    -

    The following is an example of an alias template:

    -template< typename T1, typename T2, int >
    +template< typename T1, typename T2, int N >
     class SomeType {
     public:
       T1 a;
       T2 b;
    -  int c;
     };
     
     template< typename T2 >
    @@ -643,14 +640,19 @@ using TypedefName = SomeType<char*, T2, 5>;
     

    -These are partially supported as SWIG will parse these and identify them, however, they are ignored as they are not added to the type system. A warning such as the following is issued: +SWIG supports both type aliasing and alias templates. +However, in order to use an alias template, two %template directives must be used:

    -
    -
    -example.i:13: Warning 342: The 'using' keyword in template aliasing is not fully supported yet.
    -
    -
    +
    +%template(SomeTypeBool) SomeType<char*, bool, 5>;
    +%template() TypedefName<bool>;
    +
    + +

    Firstly, the actual template is instantiated with a name to be used by the target language, as per any template being wrapped. +Secondly, the empty template instantiation, %template(), is required for the alias template. +This second requirement is necessary to add the appropriate instantiated template type into the type system as SWIG does not automatically instantiate templates. +See the Templates section for more general information on wrapping templates.

    7.2.17 Unrestricted unions

    @@ -688,7 +690,7 @@ initializers) with some limitations. The following code is correctly parsed:

     template <typename... BaseClasses> class ClassName : public BaseClasses... {
     public:
    -   ClassName (BaseClasses &&... baseClasses) : BaseClasses(baseClasses)... {}
    +  ClassName (BaseClasses &&... baseClasses) : BaseClasses(baseClasses)... {}
     }
     
    @@ -713,7 +715,24 @@ const int SIZE = sizeof...(ClassName<int, int>); In the above example SIZE is of course wrapped as a constant.

    -

    7.2.19 New string literals

    +

    7.2.19 New character literals

    + + +

    +C++11 adds support for UCS-2 and UCS-4 character literals. +These character literals are preceded by either 'u' or 'U'. +

    + +
    +char16_t a = u'a';
    +char32_t b = U'b';
    +
    + +

    +Compatibility note: SWIG-4.0.0 was the first version to support these Universal Coded Character Set (UCS) character literals. +

    + +

    7.2.20 New string literals

    SWIG supports wide string and Unicode string constants and raw string literals.

    @@ -743,7 +762,7 @@ Note: There is a bug currently where SWIG's preprocessor incorrectly parses an o inside raw string literals.

    -

    7.2.20 User-defined literals

    +

    7.2.21 User-defined literals

    @@ -810,7 +829,7 @@ OutputType var2 = 1234_suffix; OutputType var3 = 3.1416_suffix; -

    7.2.21 Thread-local storage

    +

    7.2.22 Thread-local storage

    SWIG correctly parses the thread_local keyword. For example, variables @@ -818,7 +837,7 @@ reachable by the current thread can be defined as:

     struct A {
    -   static thread_local int val;
    +  static thread_local int val;
     };
     thread_local int global_val;
     
    @@ -830,7 +849,7 @@ A variable will be thread local if accessed from different threads from the targ same way that it will be thread local if accessed from C++ code.

    -

    7.2.22 Explicitly defaulted functions and deleted functions

    +

    7.2.23 Explicitly defaulted functions and deleted functions

    SWIG handles explicitly defaulted functions, that is, = default added to a function declaration. Deleted definitions, which are also called deleted functions, have = delete added to the function declaration. @@ -858,8 +877,8 @@ For example, the C++ compiler will not compile any code which attempts to use an

     struct NoInt {
    -    void f(double i);
    -    void f(int) = delete;
    +  void f(double i);
    +  void f(int) = delete;
     };
     
    @@ -868,16 +887,17 @@ This is a C++ compile time check and SWIG does not make any attempt to detect if so in this case it is entirely possible to pass an int instead of a double to f from Java, Python etc.

    -

    7.2.23 Type long long int

    +

    7.2.24 Type long long int

    SWIG correctly parses and uses the new long long type already introduced in C99 some time ago.

    -

    7.2.24 Static assertions

    +

    7.2.25 Static assertions

    -SWIG correctly parses the new static_assert declarations. +SWIG correctly parses the new static_assert declarations (though 3.0.12 and earlier +had a bug which meant this wasn't accepted at file scope). This is a C++ compile time directive so there isn't anything useful that SWIG can do with it.

    @@ -888,7 +908,7 @@ struct Check { }; -

    7.2.25 Allow sizeof to work on members of classes without an explicit object

    +

    7.2.26 Allow sizeof to work on members of classes without an explicit object

    @@ -909,7 +929,7 @@ const int SIZE = sizeof(A::member); // does not work with C++03. Okay with C++11 8 -

    7.2.26 Exception specifications and noexcept

    +

    7.2.27 Exception specifications and noexcept

    @@ -925,7 +945,7 @@ int noex2(int) noexcept(true); int noex3(int, bool) noexcept(false); -

    7.2.27 Control and query object alignment

    +

    7.2.28 Control and query object alignment

    @@ -957,7 +977,7 @@ Use the preprocessor to work around this for now: -

    7.2.28 Attributes

    +

    7.2.29 Attributes

    @@ -970,6 +990,104 @@ int [[attr1]] i [[attr2, attr3]]; [[noreturn, nothrow]] void f [[noreturn]] (); + +

    7.2.30 Methods with ref-qualifiers

    + + +

    +C++11 non-static member functions can be declared with ref-qualifiers. +Member functions declared with a & lvalue ref-qualifiers are wrapped like any other function without ref-qualifiers. +Member functions declared with a && rvalue ref-qualifiers are ignored by default +as they are unlikely to be required from non-C++ languages where the concept of rvalue-ness +for the implied *this pointer does not apply. +The warning is hidden by default, but can be displayed as described in the section on Enabling extra warnings. +

    + +

    +Consider: +

    + +
    +struct RQ {
    +  void m1(int x) &;
    +  void m2(int x) &&;
    +};
    +
    + +

    +The only wrapped method will be the lvalue ref-qualified method m1 +and if SWIG is run with the -Wextra command-line option, the following warning will be issued indicating m2 is not wrapped: +

    + +
    +
    +example.i:7: Warning 405: Method with rvalue ref-qualifier m2(int) && ignored.
    +
    +
    + +

    +If you unignore the method as follows, wrappers for m2 will be generated: +

    + +
    +%feature("ignore", "0") RQ::m2(int x) &&;
    +struct RQ {
    +  void m1(int x) &;
    +  void m2(int x) &&;
    +};
    +
    + +

    +Inspection of the generated C++ code, will show that std::move is used on the instance +of the RQ * class: +

    + +
    +  RQ *arg1 = (RQ *) 0 ;
    +  int arg2 ;
    +
    +  arg1 = ...marshalled from target language...
    +  arg2 = ...marshalled from target language...
    +
    +  std::move(*arg1).m2(arg2);
    +
    + +

    +This will compile but when run, the move effects may not be what you want. +As stated earlier, rvalue ref-qualifiers aren't really applicable outside the world of C++. +However, if you really know what you are doing, full control over the call to the method is +possible via the low-level "action" feature. +This feature completely replaces the call to the underlying function, that is, the last line in the snippet of code above. +

    + +
    +%feature("ignore", "0") RQ::m2(int x) &&;
    +%feature("action") RQ::m2(int x) && %{
    +  RQ().m2(arg2);
    +%}
    +struct RQ {
    +  void m1(int x) &;
    +  void m2(int x) &&;
    +};
    +
    + +

    +resulting in: +

    + +
    +  RQ *arg1 = (RQ *) 0 ;
    +  int arg2 ;
    +
    +  arg1 = ...marshalled from target language...
    +  arg2 = ...marshalled from target language...
    +
    +  RQ().m2(arg2);
    +
    + +

    +Compatibility note: SWIG-4.0.0 was the first version to support ref-qualifiers. +

    7.3 Standard library changes

    @@ -994,7 +1112,8 @@ Variadic template support requires further work to provide substantial tuple wra

    The new hash tables in the STL are unordered_set, unordered_multiset, unordered_map, unordered_multimap. -These are not available in SWIG, but in principle should be easily implemented by adapting the current STL containers. +These are not available in all target languages. +Any missing support can in principle be easily implemented by adapting the current STL containers.

    7.3.4 Regular expressions

    @@ -1057,7 +1176,7 @@ It does not involve std::function.
     t = Test()
    -b = t(1,2) # invoke C++ function object
    +b = t(1, 2) # invoke C++ function object
     

    7.3.9 Type traits for metaprogramming

    @@ -1175,5 +1294,6 @@ Phew, that is a lot of hard work to get a callback working. You could just go with the more attractive option of just using double as the return type in the function declaration instead of result_of!

    + diff --git a/Doc/Manual/CPlusPlus14.html b/Doc/Manual/CPlusPlus14.html new file mode 100644 index 000000000..b162c7818 --- /dev/null +++ b/Doc/Manual/CPlusPlus14.html @@ -0,0 +1,60 @@ + + + +SWIG and C++14 + + + + + +

    8 SWIG and C++14

    + + + + + + +

    8.1 Introduction

    + + +

    This chapter gives you a brief overview about the SWIG +implementation of the C++14 standard. +There isn't much in C++14 that affects SWIG, however, work has only just begun on adding +C++14 support. +

    + +

    +Compatibility note: SWIG-4.0.0 is the first version to support any C++14 features. +

    + +

    8.2 Core language changes

    + + +

    8.2.1 Binary integer literals

    + + +

    +C++14 added binary integer literals and SWIG supports these. +Example: +

    + +
    +
    +int b = 0b101011;
    +
    +
    + +

    8.3 Standard library changes

    + + + + diff --git a/Doc/Manual/CPlusPlus17.html b/Doc/Manual/CPlusPlus17.html new file mode 100644 index 000000000..a2346660a --- /dev/null +++ b/Doc/Manual/CPlusPlus17.html @@ -0,0 +1,109 @@ + + + +SWIG and C++17 + + + + + +

    9 SWIG and C++17

    + + + + + + +

    9.1 Introduction

    + + +

    This chapter gives you a brief overview about the SWIG +implementation of the C++17 standard. +There isn't much in C++17 that affects SWIG, however, work has only just begun on adding +C++17 support. +

    + +

    +Compatibility note: SWIG-4.0.0 is the first version to support any C++17 features. +

    + +

    9.2 Core language changes

    + + +

    9.2.1 Nested namespace definitions

    + + +

    +C++17 offers a more concise syntax for defining namespaces. +SWIG has support for nested namespace definitions such as: +

    + +
    +
    +namespace A::B::C {
    +  ...
    +}
    +
    +
    + +

    +This is the equivalent to the C++98 namespace definitions: +

    + +
    +
    +namespace A {
    +  namespace B {
    +    namespace C {
    +      ...
    +    }
    +  }
    +}
    +
    +
    + +

    9.2.2 UTF-8 character literals

    + + +

    +C++17 added UTF-8 (u8) character literals. +These are of type char. +Example: +

    + +
    +
    +char a = u8'a';
    +
    +
    + +

    9.2.3 Hexadecimal floating literals

    + + +

    +C++17 added hexadecimal floating literals. +For example: +

    + +
    +
    +double f = 0xF.68p2;
    +
    +
    + +

    9.3 Standard library changes

    + + + + diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html index 26f0c740e..1fc2d211e 100644 --- a/Doc/Manual/CSharp.html +++ b/Doc/Manual/CSharp.html @@ -6,7 +6,7 @@ -

    20 SWIG and C#

    +

    22 SWIG and C#

    @@ -54,7 +55,7 @@ -

    20.1 Introduction

    +

    22.1 Introduction

    @@ -63,18 +64,18 @@ The wrapper code implementation uses C# and the Platform Invoke (PInvoke) interf The PInvoke interface has been chosen over Microsoft's Managed C++ interface as it is portable to both Microsoft Windows and non-Microsoft platforms. PInvoke is part of the ECMA/ISO C# specification. It is also better suited for robust production environments due to the Managed C++ flaw called the -Mixed DLL Loading Problem. +Mixed DLL Loading Problem. SWIG C# works equally well on non-Microsoft operating systems such as Linux, Solaris and Apple Mac using -Mono and Portable.NET. +Mono and Portable.NET.

    To get the most out of this chapter an understanding of interop is required. -The Microsoft Developer Network (MSDN) has a good reference guide in a section titled "Interop Marshaling". -Monodoc, available from the Mono project, has a very useful section titled Interop with native libraries. +The Microsoft Developer Network (MSDN) has a good reference guide in a section titled "Interop Marshaling". +Monodoc, available from the Mono project, has a very useful section titled Interop with native libraries.

    -

    20.1.1 SWIG 2 Compatibility

    +

    22.1.1 SWIG 2 Compatibility

    @@ -82,7 +83,7 @@ In order to minimize name collisions between names generated based on input to S

    -

    20.1.2 Additional command line options

    +

    22.1.2 Additional command line options

    @@ -134,7 +135,7 @@ Note that the file extension (.cs) will not be automatically added and needs to Due to possible compiler limits it is not advisable to use -outfile for large projects.

    -

    20.2 Differences to the Java module

    +

    22.2 Differences to the Java module

    @@ -231,8 +232,8 @@ javacode -> cscode javaimports -> csimports javabody -> csbody javafinalize -> csfinalize -javadestruct -> csdestruct -javadestruct_derived -> csdestruct_derived +javadestruct -> csdisposing and csdispose +javadestruct_derived -> csdisposing_derived and csdispose_derived javainterfacecode -> csinterfacecode

    @@ -544,14 +545,18 @@ unless the imclassname attribute is specified in the Cygwin or MinGW environment for automatic configuration of the example makefiles. -Any one of the three C# compilers (Portable.NET, Mono or Microsoft) can be detected from within a Cygwin or Mingw environment if installed in your path. +Any one of the C# compilers (Mono or Microsoft) can be detected from within a Cygwin or Mingw environment if installed in your path. -

    20.3 Void pointers

    +

    22.3 Void pointers

    @@ -569,7 +574,7 @@ void * f(void *v); -

    20.4 C# Arrays

    +

    22.4 C# Arrays

    @@ -581,7 +586,7 @@ with one of the following three approaches; namely the SWIG C arrays library, P/ pinned arrays.

    -

    20.4.1 The SWIG C arrays library

    +

    22.4.1 The SWIG C arrays library

    @@ -598,7 +603,7 @@ For the %array_functions example, the equivalent usage would be:

     SWIGTYPE_p_double a = example.new_doubleArray(10);  // Create an array
     for (int i=0; i<10; i++)
    -  example.doubleArray_setitem(a,i,2*i);             // Set a value
    +  example.doubleArray_setitem(a, i, 2*i);           // Set a value
     example.print_array(a);                             // Pass to C
     example.delete_doubleArray(a);                      // Destroy array
     
    @@ -618,7 +623,7 @@ example.print_array(c.cast()); // Pass to C -

    20.4.2 Managed arrays using P/Invoke default array marshalling

    +

    22.4.2 Managed arrays using P/Invoke default array marshalling

    @@ -638,7 +643,7 @@ passing a direct reference as described in the next section.

    For more information on the subject, see the -Default Marshaling for Arrays article +Default Marshaling for Arrays article on MSDN.

    @@ -673,7 +678,7 @@ As a result, we get the following method in the module class:
     public static void myArrayCopy(int[] sourceArray, int[] targetArray, int nitems) {
    -    examplePINVOKE.myArrayCopy(sourceArray, targetArray, nitems);
    +  examplePINVOKE.myArrayCopy(sourceArray, targetArray, nitems);
     }
     
    @@ -745,7 +750,7 @@ and intermediary class method -

    20.4.3 Managed arrays using pinning

    +

    22.4.3 Managed arrays using pinning

    @@ -758,7 +763,7 @@ another thread may produce enough garbage to trigger garbage collection.

    -For more information, see the fixed statement in the C# language reference. +For more information, see the fixed statement in the C# language reference.

    @@ -840,7 +845,7 @@ public static extern void myArrayCopy(global::System.IntPtr jarg1, global::Syste -

    20.5 C# Exceptions

    +

    22.5 C# Exceptions

    @@ -937,7 +942,7 @@ set so should only be used when a C# exception is not created.

    -

    20.5.1 C# exception example using "check" typemap

    +

    22.5.1 C# exception example using "check" typemap

    @@ -993,9 +998,9 @@ When the following C# code is executed:

     public class runme {
    -    static void Main() {
    -      example.positivesonly(-1);
    -    }
    +  static void Main() {
    +    example.positivesonly(-1);
    +  }
     }
     
    @@ -1021,18 +1026,18 @@ Now let's analyse the generated code to gain a fuller understanding of the typem
     SWIGEXPORT void SWIGSTDCALL CSharp_positivesonly(int jarg1) {
    -    int arg1 ;
    -    
    -    arg1 = (int)jarg1; 
    -    
    -    if (arg1 < 0) {
    -        SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException,
    -                                               "only positive numbers accepted", "number");
    -        return ;
    -    }
    -    
    -    positivesonly(arg1);
    -    
    +  int arg1 ;
    +
    +  arg1 = (int)jarg1;
    +
    +  if (arg1 < 0) {
    +    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException,
    +      "only positive numbers accepted", "number");
    +    return ;
    +  }
    +
    +  positivesonly(arg1);
    +
     }
     
    @@ -1119,7 +1124,7 @@ method and C# code does not handle pending exceptions via the canthrow attribute Actually it will issue this warning for any function beginning with SWIG_CSharpSetPendingException.

    -

    20.5.2 C# exception example using %exception

    +

    22.5.2 C# exception example using %exception

    @@ -1155,18 +1160,17 @@ The generated unmanaged code this time catches the C++ exception and converts it

     SWIGEXPORT void SWIGSTDCALL CSharp_negativesonly(int jarg1) {
    -    int arg1 ;
    -    
    -    arg1 = (int)jarg1; 
    -    
    -    try {
    -        negativesonly(arg1);
    -        
    -    } catch (std::out_of_range e) {
    -        SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, e.what());
    -        return ;
    -    }
    -    
    +  int arg1 ;
    +
    +  arg1 = (int)jarg1;
    +
    +  try {
    +    negativesonly(arg1);
    +
    +  } catch (std::out_of_range e) {
    +    SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, e.what());
    +    return ;
    +  }
     }
     
    @@ -1185,7 +1189,7 @@ The managed code generated does check for the pending exception as mentioned ear -

    20.5.3 C# exception example using exception specifications

    +

    22.5.3 C# exception example using exception specifications

    @@ -1221,19 +1225,18 @@ SWIG generates a try catch block with the throws typemap code in the catch handl

     SWIGEXPORT void SWIGSTDCALL CSharp_evensonly(int jarg1) {
    -    int arg1 ;
    -    
    -    arg1 = (int)jarg1; 
    -    try {
    -        evensonly(arg1);
    +  int arg1 ;
    +
    +  arg1 = (int)jarg1;
    +  try {
    +    evensonly(arg1);
    +  }
    +  catch(std::out_of_range &_e) {
    +    {
    +      SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentException, (&_e)->what(), NULL);
    +      return ;
         }
    -    catch(std::out_of_range &_e) {
    -      {
    -          SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentException, (&_e)->what(), NULL);
    -          return ;
    -      }
    -    }
    -    
    +  }
     }
     
    @@ -1242,7 +1245,7 @@ SWIGEXPORT void SWIGSTDCALL CSharp_evensonly(int jarg1) { Multiple catch handlers are generated should there be more than one exception specifications declared.

    -

    20.5.4 Custom C# ApplicationException example

    +

    22.5.4 Custom C# ApplicationException example

    @@ -1376,7 +1379,7 @@ try { -

    20.6 C# Directors

    +

    22.6 C# Directors

    @@ -1389,7 +1392,7 @@ The following sections provide information on the C# director implementation and However, the Java directors section should also be read in order to gain more insight into directors.

    -

    20.6.1 Directors example

    +

    22.6.1 Directors example

    @@ -1510,7 +1513,7 @@ CSharpDerived - UIntMethod(123) -

    20.6.2 Directors implementation

    +

    22.6.2 Directors implementation

    @@ -1572,9 +1575,9 @@ public class Base : global::System.IDisposable { private void SwigDirectorConnect() { if (SwigDerivedClassHasMethod("UIntMethod", swigMethodTypes0)) - swigDelegate0 = new SwigDelegateBase_0(SwigDirectorUIntMethod); + swigDelegate0 = new SwigDelegateBase_0(SwigDirectorMethodUIntMethod); if (SwigDerivedClassHasMethod("BaseBoolMethod", swigMethodTypes1)) - swigDelegate1 = new SwigDelegateBase_1(SwigDirectorBaseBoolMethod); + swigDelegate1 = new SwigDelegateBase_1(SwigDirectorMethodBaseBoolMethod); examplePINVOKE.Base_director_connect(swigCPtr, swigDelegate0, swigDelegate1); } @@ -1584,16 +1587,16 @@ public class Base : global::System.IDisposable { return hasDerivedMethod; } - private uint SwigDirectorUIntMethod(uint x) { + private uint SwigDirectorMethodUIntMethod(uint x) { return UIntMethod(x); } - private void SwigDirectorBaseBoolMethod(global::System.IntPtr b, bool flag) { + private void SwigDirectorMethodBaseBoolMethod(global::System.IntPtr b, bool flag) { BaseBoolMethod(new Base(b, false), flag); } - internal delegate uint SwigDelegateBase_0(uint x); - internal delegate void SwigDelegateBase_1(global::System.IntPtr b, bool flag); + public delegate uint SwigDelegateBase_0(uint x); + public delegate void SwigDelegateBase_1(global::System.IntPtr b, bool flag); private SwigDelegateBase_0 swigDelegate0; private SwigDelegateBase_1 swigDelegate1; @@ -1617,9 +1620,9 @@ It uses a support method, SwigDerivedClassHasMethod(), which simply use BaseBoolMethod, with the list of required parameter types, exists in a subclass. If it does not exist, the delegate is not initialised as there is no need for unmanaged code to call back into managed C# code. However, if there is an overridden method in any subclass, the delegate is required. -It is then initialised to the SwigDirectorBaseBoolMethod which in turn will call BaseBoolMethod if invoked. +It is then initialised to the SwigDirectorMethodBaseBoolMethod which in turn will call BaseBoolMethod if invoked. The delegate is not initialised to the BaseBoolMethod directly as quite often types will need marshalling from the unmanaged type -to the managed type in which case an intermediary method (SwigDirectorBaseBoolMethod) is required for the marshalling. +to the managed type in which case an intermediary method (SwigDirectorMethodBaseBoolMethod) is required for the marshalling. In this case, the C# Base class needs to be created from the unmanaged IntPtr type.

    @@ -1643,20 +1646,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Base_director_connect(void *objarg, class SwigDirector_Base : public Base, public Swig::Director { public: - SwigDirector_Base(); - virtual unsigned int UIntMethod(unsigned int x); - virtual ~SwigDirector_Base(); - virtual void BaseBoolMethod(Base const &b, bool flag); + SwigDirector_Base(); + virtual unsigned int UIntMethod(unsigned int x); + virtual ~SwigDirector_Base(); + virtual void BaseBoolMethod(Base const &b, bool flag); - typedef unsigned int (SWIGSTDCALL* SWIG_Callback0_t)(unsigned int); - typedef void (SWIGSTDCALL* SWIG_Callback1_t)(void *, unsigned int); - void swig_connect_director(SWIG_Callback0_t callbackUIntMethod, - SWIG_Callback1_t callbackBaseBoolMethod); + typedef unsigned int (SWIGSTDCALL* SWIG_Callback0_t)(unsigned int); + typedef void (SWIGSTDCALL* SWIG_Callback1_t)(void *, unsigned int); + void swig_connect_director(SWIG_Callback0_t callbackUIntMethod, + SWIG_Callback1_t callbackBaseBoolMethod); private: - SWIG_Callback0_t swig_callbackUIntMethod; - SWIG_Callback1_t swig_callbackBaseBoolMethod; - void swig_init_callbacks(); + SWIG_Callback0_t swig_callbackUIntMethod; + SWIG_Callback1_t swig_callbackBaseBoolMethod; + void swig_init_callbacks(); }; void SwigDirector_Base::swig_connect_director(SWIG_Callback0_t callbackUIntMethod, @@ -1682,7 +1685,7 @@ void SwigDirector_Base::BaseBoolMethod(Base const &b, bool flag) { unsigned int jflag ; if (!swig_callbackBaseBoolMethod) { - Base::BaseBoolMethod(b,flag); + Base::BaseBoolMethod(b, flag); return; } else { jb = (Base *) &b; @@ -1693,7 +1696,32 @@ void SwigDirector_Base::BaseBoolMethod(Base const &b, bool flag) { -

    20.6.3 Director caveats

    +

    +The delegates from the above example are public by default: +

    + +
    +
    +  public delegate uint SwigDelegateBase_0(uint x);
    +  public delegate void SwigDelegateBase_1(global::System.IntPtr b, bool flag);
    +
    +
    + +

    +These can be changed if desired via the csdirectordelegatemodifiers +%feature directive. +For example, using %feature("csdirectordelegatemodifiers") "internal" +before SWIG parses the Base class will change all the delegates to internal: +

    + +
    +
    +  internal delegate uint SwigDelegateBase_0(uint x);
    +  internal delegate void SwigDelegateBase_1(global::System.IntPtr b, bool flag);
    +
    +
    + +

    22.6.3 Director caveats

    @@ -1741,11 +1769,11 @@ However, a call from C# to CSharpDefaults.DefaultMethod() will of cours should pass the call on to CSharpDefaults.DefaultMethod(int)using the C++ default value, as shown above.

    -

    20.7 Multiple modules

    +

    22.7 Multiple modules

    -When using multiple modules it is is possible to compile each SWIG generated wrapper +When using multiple modules it is possible to compile each SWIG generated wrapper into a different assembly. However, by default the generated code may not compile if generated classes in one assembly use generated classes in another assembly. @@ -1776,7 +1804,7 @@ the [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrows if you don't want users to easily stumble upon these so called 'internal workings' of the wrappers.

    -

    20.8 C# Typemap examples

    +

    22.8 C# Typemap examples

    This section includes a few examples of typemaps. For more examples, you @@ -1784,7 +1812,7 @@ might look at the files "csharp.swg" and "typemaps.i" in the SWIG library. -

    20.8.1 Memory management when returning references to member variables

    +

    22.8.1 Memory management when returning references to member variables

    @@ -1800,7 +1828,7 @@ Consider the following C++ code:

     struct Wheel {
       int size;
    -  Wheel(int sz) : size(sz) {}
    +  Wheel(int sz = 0) : size(sz) {}
     };
     
     class Bike {
    @@ -1819,12 +1847,12 @@ and the following usage from C# after running the code through SWIG:
     
     
    -      Wheel wheel = new Bike(10).getWheel();
    -      Console.WriteLine("wheel size: " + wheel.size);
    -      // Simulate a garbage collection
    -      global::System.GC.Collect();
    -      global::System.GC.WaitForPendingFinalizers();
    -      global::System.Console.WriteLine("wheel size: " + wheel.size);
    +  Wheel wheel = new Bike(10).getWheel();
    +  Console.WriteLine("wheel size: " + wheel.size);
    +  // Simulate a garbage collection
    +  global::System.GC.Collect();
    +  global::System.GC.WaitForPendingFinalizers();
    +  global::System.Console.WriteLine("wheel size: " + wheel.size);
     
    @@ -1908,7 +1936,7 @@ public class Bike : global::System.IDisposable { Note the addReference call.

    -

    20.8.2 Memory management for objects passed to the C++ layer

    +

    22.8.2 Memory management for objects passed to the C++ layer

    @@ -1940,10 +1968,10 @@ and usage from C++

    -    Container container;
    -    Element element(20);
    -    container.setElement(&element);
    -    cout << "element.value: " << container.getElement()->value << endl;
    +  Container container;
    +  Element element(20);
    +  container.setElement(&element);
    +  cout << "element.value: " << container.getElement()->value << endl;
     
    @@ -1953,27 +1981,27 @@ and more or less equivalent usage from C#
    -      Container container = new Container();
    -      Element element = new Element(20);
    -      container.setElement(element);
    +  Container container = new Container();
    +  Element element = new Element(20);
    +  container.setElement(element);
     

    The C++ code will always print out 20, but the value printed out may not be this in the C# equivalent code. -In order to understand why, consider a garbage collection occuring... +In order to understand why, consider a garbage collection occurring...

    -      Container container = new Container();
    -      Element element = new Element(20);
    -      container.setElement(element);
    -      Console.WriteLine("element.value: " + container.getElement().value);
    -      // Simulate a garbage collection
    -      global::System.GC.Collect();
    -      global::System.GC.WaitForPendingFinalizers();
    -      global::System.Console.WriteLine("element.value: " + container.getElement().value);
    +  Container container = new Container();
    +  Element element = new Element(20);
    +  container.setElement(element);
    +  Console.WriteLine("element.value: " + container.getElement().value);
    +  // Simulate a garbage collection
    +  global::System.GC.Collect();
    +  global::System.GC.WaitForPendingFinalizers();
    +  global::System.Console.WriteLine("element.value: " + container.getElement().value);
     
    @@ -1992,42 +2020,55 @@ public class Container : global::System.IDisposable { // Ensure that the GC doesn't collect any Element set from C# // as the underlying C++ class stores a shallow copy private Element elementReference; - private global::System.Runtime.InteropServices.HandleRef getCPtrAndAddReference(Element element) { - elementReference = element; - return Element.getCPtr(element); - } public void setElement(Element e) { - examplePINVOKE.Container_setElement(swigCPtr, getCPtrAndAddReference(e)); + examplePINVOKE.Container_setElement(swigCPtr, Element.getCPtr(e)); + elementReference = e; } }

    -The following typemaps will generate the desired code. -The 'csin' typemap matches the input parameter type for the setElement method. -The 'cscode' typemap simply adds in the specified code into the C# proxy class. +The following typemaps can be used to generate this code:

    -%typemap(csin) Element *e "getCPtrAndAddReference($csinput)"
    -
     %typemap(cscode) Container %{
       // Ensure that the GC doesn't collect any Element set from C#
       // as the underlying C++ class stores a shallow copy
       private Element elementReference;
    -  private global::System.Runtime.InteropServices.HandleRef getCPtrAndAddReference(Element element) {
    -    elementReference = element;
    -    return Element.getCPtr(element);
    -  }
     %}
    +
    +%typemap(csin,
    +         post="      elementReference = $csinput;"
    +         ) Element *e "Element.getCPtr($csinput)"
    +
    +
    + +

    +The 'cscode' typemap simply adds in the specified code into the C# proxy class. +The 'csin' typemap matches the input parameter type and name for the setElement method and +the 'post' typemap attribute allows adding code after the PInvoke call. +The 'post' code is generated into a finally block after the PInvoke call so the resulting code isn't quite +as mentioned earlier, setElement is actually: +

    + +
    +
    +  public void setElement(Element e) {
    +    try {
    +      examplePINVOKE.Container_setElement(swigCPtr, Element.getCPtr(e));
    +    } finally {
    +      elementReference = e;
    +    }
    +  }
     
    -

    20.8.3 Date marshalling using the csin typemap and associated attributes

    +

    22.8.3 Date marshalling using the csin typemap and associated attributes

    @@ -2100,7 +2141,7 @@ The CDate & and const CDate & C# code is generated fro

    where '$csclassname' is translated into the proxy class name, CDate and '$csinput' is translated into the name of the parameter, eg dateIn. -From C#, the intention is then to call into a modifed API with something like: +From C#, the intention is then to call into a modified API with something like:

    @@ -2134,7 +2175,7 @@ The typemaps to achieve this are shown below. %typemap(csin, pre=" CDate temp$csinput = new CDate();", post=" $csinput = new System.DateTime(temp$csinput.getYear()," - " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", + " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", cshin="out $csinput" ) CDate & "$csclassname.getCPtr(temp$csinput)" @@ -2240,7 +2281,7 @@ will be possible with the following CDate * typemaps %typemap(csin, pre=" CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day);", post=" $csinput = new System.DateTime(temp$csinput.getYear()," - " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", + " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", cshin="ref $csinput" ) CDate * "$csclassname.getCPtr(temp$csinput)" @@ -2279,7 +2320,7 @@ The subtractYears method is nearly identical to the above addYears< %typemap(csin, pre=" using (CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day)) {", post=" $csinput = new System.DateTime(temp$csinput.getYear()," - " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", + " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", terminator=" } // terminate temp$csinput using block", cshin="ref $csinput" ) CDate * @@ -2313,7 +2354,7 @@ public class example {
    -

    20.8.4 A date example demonstrating marshalling of C# properties

    +

    22.8.4 A date example demonstrating marshalling of C# properties

    @@ -2351,7 +2392,7 @@ The typemap type required is thus CDate *. Given that the previous sect %typemap(csin, pre=" CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day);", post=" $csinput = new System.DateTime(temp$csinput.getYear()," - " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", + " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", cshin="ref $csinput" ) CDate * "$csclassname.getCPtr(temp$csinput)" @@ -2413,7 +2454,7 @@ Some points to note:

  • The 'csin' typemap has 'pre', 'post' and 'cshin' attributes, and these are all ignored in the property set. The code in these attributes must instead be replicated within the 'csvarin' typemap. The line creating the temp$csinput variable is such an example; it is identical to what is in the 'pre' attribute. -

    20.8.5 Date example demonstrating the 'pre' and 'post' typemap attributes for directors

    +

    22.8.5 Date example demonstrating the 'pre' and 'post' typemap attributes for directors

    @@ -2456,7 +2497,7 @@ The generated proxy class code will then contain the following wrapper for calli

     ...
    -  private void SwigDirectorsomeCallback(global::System.IntPtr date) {
    +  private void SwigDirectorMethodsomeCallback(global::System.IntPtr date) {
         System.DateTime tempdate = new System.DateTime();
         try {
           someCallback(out tempdate);
    @@ -2475,7 +2516,7 @@ Pay special attention to the memory management issues, using these attributes.
     

    -

    20.8.6 Turning wrapped classes into partial classes

    +

    22.8.6 Turning proxy classes into partial classes

    @@ -2575,7 +2616,97 @@ demonstrating that the class contains methods calling both unmanaged code - The following example is an alternative approach to adding managed code to the generated proxy class.

    -

    20.8.7 Extending proxy classes with additional C# code

    +

    22.8.7 Turning proxy classes into sealed classes

    + + +

    +The technique in the previous section can be used to make the proxy class a sealed class. +Consider a C++ class NotABaseClass that you don't want to be derived from in C#: +

    + +
    +
    +struct NotABaseClass {
    +  NotABaseClass();
    +  ~NotABaseClass();
    +};
    +
    +
    + +

    +The default C# proxy class method generated with Dispose method is: +

    + +
    +
    +public class NotABaseClass : global::System.IDisposable {
    +  ...
    +  public virtual void Dispose() {
    +    ...
    +  }
    +}
    +
    +
    + +

    +The csclassmodifiers typemap can be used to modify the class modifiers and +the csmethodmodifiers feature can be used on the destructor to modify the proxy's Dispose method: +

    + +
    +
    +%typemap(csclassmodifiers) NotABaseClass "public sealed class"
    +%csmethodmodifiers NotABaseClass::~NotABaseClass "public /*virtual*/";
    +
    +
    + +

    +The relevant generated code is thus: +

    + +
    +
    +public sealed class NotABaseClass : global::System.IDisposable {
    +  ...
    +  public /*virtual*/ void Dispose() {
    +    ...
    +  }
    +}
    +
    +
    + +

    +Any attempt to derive from the NotABaseClass in C# will result in a C# compiler error, for example: +

    + +
    +
    +public class Derived : NotABaseClass {
    +};
    +
    +
    +
    +
    +runme.cs(6,14): error CS0509: `Derived': cannot derive from sealed type `NotABaseClass'
    +
    +
    + +

    +Finally, if you get a warning about use of 'protected' in the generated base class: +

    + +
    +
    +NotABaseClass.cs(14,18): warning CS0628: `NotABaseClass.swigCMemOwn': new protected member declared in sealed class
    +
    +
    + +

    +Either suppress the warning or modify the generated code by copying and tweaking the default +'csbody' typemap code in csharp.swg by modifying swigCMemOwn to not be protected. +

    + +

    22.8.8 Extending proxy classes with additional C# code

    @@ -2614,13 +2745,13 @@ public class ExtendMe : global::System.IDisposable {

    -

    20.8.8 Underlying type for enums

    +

    22.8.9 Underlying type for enums

    C# enums use int as the underlying type for each enum item. If you wish to change the underlying type to something else, then use the csbase typemap. -For example when your C++ code uses a value larget than int, this is necessary as the C# compiler will not compile values which are too large to fit into an int. +For example when your C++ code uses a value larger than int, this is necessary as the C# compiler will not compile values which are too large to fit into an int. Here is an example:

    diff --git a/Doc/Manual/Chicken.html b/Doc/Manual/Chicken.html index 820d01fde..3a80811bd 100644 --- a/Doc/Manual/Chicken.html +++ b/Doc/Manual/Chicken.html @@ -8,7 +8,7 @@ -

    21 SWIG and Chicken

    +

    23 SWIG and Chicken

    -

    21.3 TinyCLOS

    +

    23.3 TinyCLOS

    The author of TinyCLOS, Gregor Kiczales, describes TinyCLOS as: - "Tiny CLOS is a Scheme implementation of a `kernelized' CLOS, with a + "Tiny CLOS is a Scheme implementation of a 'kernelized' CLOS, with a metaobject protocol. The implementation is even simpler than - the simple CLOS found in `The Art of the Metaobject Protocol,' + the simple CLOS found in 'The Art of the Metaobject Protocol', weighing in at around 850 lines of code, including (some) comments and documentation."

    @@ -333,7 +333,7 @@

    -

    21.4 Linkage

    +

    23.4 Linkage

    @@ -354,7 +354,7 @@

    -

    21.4.1 Static binary or shared library linked at compile time

    +

    23.4.1 Static binary or shared library linked at compile time

    We can easily use csc to build a static binary.

    @@ -395,7 +395,7 @@ in which case the test script does not need to be linked with example.so. The t be run with csi.

    -

    21.4.2 Building chicken extension libraries

    +

    23.4.2 Building chicken extension libraries

    Building a shared library like in the above section only works if the library @@ -453,7 +453,7 @@ distributed and used by anyone, even if SWIG is not installed.

    See the Examples/chicken/egg directory in the SWIG source for an example that builds two eggs, one using the first method and one using the second method.

    -

    21.4.3 Linking multiple SWIG modules with TinyCLOS

    +

    23.4.3 Linking multiple SWIG modules with TinyCLOS

    Linking together multiple modules that share type information using the %import @@ -477,7 +477,7 @@ with (declare (uses ...)). To create an extension library or an egg, just create a module_load.scm file that (declare (uses ...)) all the modules.

    -

    21.5 Typemaps

    +

    23.5 Typemaps

    @@ -486,7 +486,7 @@ all the modules.

    Lib/chicken/chicken.swg.

    -

    21.6 Pointers

    +

    23.6 Pointers

    @@ -519,7 +519,7 @@ all the modules.

    type. flags is either zero or SWIG_POINTER_DISOWN (see below).

    -

    21.6.1 Garbage collection

    +

    23.6.1 Garbage collection

    If the owner flag passed to SWIG_NewPointerObj is 1, NewPointerObj will add a @@ -550,7 +550,7 @@ all the modules.

    must be called manually.

    -

    21.7 Unsupported features and known problems

    +

    23.7 Unsupported features and known problems

    -

    21.7.1 TinyCLOS problems with Chicken version <= 1.92

    +

    23.7.1 TinyCLOS problems with Chicken version <= 1.92

    In Chicken versions equal to or below 1.92, TinyCLOS has a limitation such that generic methods do not properly work on methods diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 3f283ecb9..57aef5b8a 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -46,6 +46,11 @@

  • Standard library changes
  • Some typemap examples
      @@ -482,6 +544,9 @@
    • Usage
  • Typemaps and overloading +
  • More about %apply and %clear
  • Passing data between typemaps
  • C++ "this" pointer @@ -490,7 +555,7 @@ -

    12 Customization Features

    +

    14 Customization Features

    @@ -518,7 +583,7 @@
    -

    13 Contracts

    +

    15 Contracts

    @@ -531,7 +596,7 @@
    -

    14 Variable Length Arguments

    +

    16 Variable Length Arguments

    @@ -549,7 +614,55 @@
    -

    15 Warning Messages

    +

    17 SWIG and Doxygen Translation

    + + + + + +

    18 Warning Messages

    @@ -568,7 +681,8 @@
  • Preprocessor (200-299)
  • C/C++ Parser (300-399)
  • Types and typemaps (400-499) -
  • Code generation (500-599) +
  • Code generation (500-559) +
  • Doxygen comments (560-599)
  • Language module specific (700-899)
  • User defined (900-999) @@ -577,7 +691,7 @@ -

    16 Working with Modules

    +

    19 Working with Modules

    @@ -593,7 +707,7 @@
    -

    17 Using SWIG with ccache - ccache-swig(1) manpage

    +

    20 Using SWIG with ccache - ccache-swig(1) manpage

    @@ -619,91 +733,7 @@
    -

    18 SWIG and Allegro Common Lisp

    - - - - - -

    19 SWIG and Android

    +

    21 SWIG and Android

    @@ -721,7 +751,7 @@
    -

    20 SWIG and C#

    +

    22 SWIG and C#

    @@ -760,7 +790,8 @@
  • Date marshalling using the csin typemap and associated attributes
  • A date example demonstrating marshalling of C# properties
  • Date example demonstrating the 'pre' and 'post' typemap attributes for directors -
  • Turning wrapped classes into partial classes +
  • Turning proxy classes into partial classes +
  • Turning proxy classes into sealed classes
  • Extending proxy classes with additional C# code
  • Underlying type for enums @@ -768,45 +799,7 @@ -

    21 SWIG and Chicken

    - - - - - -

    22 SWIG and D

    +

    23 SWIG and D

    @@ -840,7 +833,7 @@
    -

    23 SWIG and Go

    +

    24 SWIG and Go

    @@ -884,7 +877,7 @@
    -

    24 SWIG and Guile

    +

    25 SWIG and Guile

    @@ -907,19 +900,20 @@
  • Smobs
  • Garbage Collection -
  • Exception Handling -
  • Procedure documentation -
  • Procedures with setters -
  • GOOPS Proxy Classes +
  • Native Guile pointers +
  • Exception Handling +
  • Procedure documentation +
  • Procedures with setters +
  • GOOPS Proxy Classes -

    25 SWIG and Java

    +

    26 SWIG and Java

    @@ -1008,12 +1002,16 @@
  • Director threading issues
  • Director performance tuning
  • Java exceptions from directors +
  • Accessing protected members
  • Common customization features @@ -1069,7 +1067,7 @@ -

    26 SWIG and Javascript

    +

    27 SWIG and Javascript

    @@ -1111,29 +1109,6 @@
    -

    27 SWIG and Common Lisp

    - - - - -

    28 SWIG and Lua

    @@ -1202,108 +1177,7 @@ -

    29 SWIG and Modula-3

    - - - - - -

    30 SWIG and MzScheme/Racket

    - - - - - -

    31 SWIG and Ocaml

    - - - - - -

    32 SWIG and Octave

    +

    29 SWIG and Octave

    @@ -1343,7 +1217,7 @@
    -

    33 SWIG and Perl5

    +

    30 SWIG and Perl5

    @@ -1419,7 +1293,7 @@
    -

    34 SWIG and PHP

    +

    31 SWIG and PHP

    @@ -1460,31 +1334,7 @@
    -

    35 SWIG and Pike

    - - - - - -

    36 SWIG and Python

    +

    32 SWIG and Python

    @@ -1499,7 +1349,8 @@
  • Using your module
  • Compilation of C++ extensions
  • Compiling for 64-bit platforms -
  • Building Python Extensions under Windows +
  • Building Python extensions under Windows +
  • Additional Python commandline options
  • A tour of basic C/C++ wrapping
  • Memory management -
  • Python 2.2 and classic classes
  • Cross language polymorphism
  • Tips and techniques
  • Docstring Features @@ -1611,11 +1467,16 @@
  • Byte string output conversion
  • Python 2 Unicode +
  • Support for Multithreaded Applications + -

    37 SWIG and R

    +

    33 SWIG and R

    @@ -1631,7 +1492,7 @@
    -

    38 SWIG and Ruby

    +

    34 SWIG and Ruby

    @@ -1769,7 +1630,7 @@
    -

    39 SWIG and Scilab

    +

    35 SWIG and Scilab

    @@ -1800,7 +1661,7 @@
  • Pointers
  • Structures @@ -1838,7 +1699,7 @@ -

    40 SWIG and Tcl

    +

    36 SWIG and Tcl

    @@ -1904,7 +1765,74 @@
    -

    41 Extending SWIG to support new languages

    +

    37 SWIG and MzScheme/Racket

    + + + + + +

    38 SWIG and OCaml

    + + + + + +

    39 Extending SWIG to support new languages

    @@ -1962,8 +1890,13 @@
  • Running the test-suite
  • Documentation -
  • Prerequisites for adding a new language module to the SWIG distribution
  • Coding style guidelines +
  • Target language status + +
  • Prerequisites for adding a new language module to the SWIG distribution
  • Debugging Options
  • Guide to parse tree nodes diff --git a/Doc/Manual/Contract.html b/Doc/Manual/Contract.html index 4b4995819..93fb8c003 100644 --- a/Doc/Manual/Contract.html +++ b/Doc/Manual/Contract.html @@ -7,7 +7,7 @@ -

    13 Contracts

    +

    15 Contracts

      @@ -39,7 +39,7 @@ When one of the rules is violated by a script, a runtime exception is generated rather than having the program continue to execute.

      -

      13.1 The %contract directive

      +

      15.1 The %contract directive

      @@ -51,9 +51,9 @@ is a simple example:

       %contract sqrt(double x) {
       require:
      -    x >= 0;
      +  x >= 0;
       ensure:
      -    sqrt >= 0;
      +  sqrt >= 0;
       }
       
       ...
      @@ -95,7 +95,7 @@ RuntimeError: Contract violation: require: (arg1>=0)
       
    -

    13.2 %contract and classes

    +

    15.2 %contract and classes

    @@ -106,20 +106,20 @@ The %contract directive can also be applied to class methods and constr

     %contract Foo::bar(int x, int y) {
     require:
    -   x > 0;
    +  x > 0;
     ensure:
    -   bar > 0;
    +  bar > 0;
     }
     
     %contract Foo::Foo(int a) {
     require:
    -   a > 0;
    +  a > 0;
     }
     
     class Foo {
     public:
    -    Foo(int);
    -    int bar(int, int);
    +  Foo(int);
    +  int bar(int, int);
     };
     
    @@ -133,7 +133,7 @@ Thus, any contract that you specified for a base class will also be attached to
     class Spam : public Foo {
     public:
    -   int bar(int,int);    // Gets contract defined for Foo::bar(int,int)
    +  int bar(int, int);    // Gets contract defined for Foo::bar(int, int)
     };
     
    @@ -146,22 +146,22 @@ In addition to this, separate contracts can be applied to both the base class an
     %contract Foo::bar(int x, int) {
     require:
    -    x > 0;
    +  x > 0;
     }
     
     %contract Spam::bar(int, int y) {
     require:
    -    y > 0;
    +  y > 0;
     }
     
     class Foo {
     public:
    -    int bar(int,int);   // Gets Foo::bar contract.
    +  int bar(int, int);   // Gets Foo::bar contract.
     };
     
     class Spam : public Foo {
     public:
    -     int bar(int,int);   // Gets Foo::bar and Spam::bar contract
    +  int bar(int, int);   // Gets Foo::bar and Spam::bar contract
     };
     
    @@ -174,7 +174,7 @@ specified for the derived class all must hold. In the above example, this means that both the arguments to Spam::bar must be positive.

    -

    13.3 Constant aggregation and %aggregate_check

    +

    15.3 Constant aggregation and %aggregate_check

    @@ -225,7 +225,7 @@ function can be used in contracts. For example: %contract move(SomeObject *, int direction, in) { require: - check_direction(direction); + check_direction(direction); } #define UP 1 @@ -246,7 +246,7 @@ Alternatively, it can be used in typemaps and other directives. For example: %aggregate_check(int, check_direction, UP, DOWN, RIGHT, LEFT); %typemap(check) int direction { - if (!check_direction($1)) SWIG_exception(SWIG_ValueError, "Bad direction"); + if (!check_direction($1)) SWIG_exception(SWIG_ValueError, "Bad direction"); } #define UP 1 @@ -263,7 +263,7 @@ Regrettably, there is no automatic way to perform similar checks with enums valu release.

    -

    13.4 Notes

    +

    15.4 Notes

    diff --git a/Doc/Manual/Customization.html b/Doc/Manual/Customization.html index 8705534f9..328bc2391 100644 --- a/Doc/Manual/Customization.html +++ b/Doc/Manual/Customization.html @@ -7,7 +7,7 @@ -

    12 Customization Features

    +

    14 Customization Features

      @@ -46,7 +46,7 @@ of exception handling is presented. Then, a more general-purpose customization mechanism known as "features" is described.

      -

      12.1 Exception handling with %exception

      +

      14.1 Exception handling with %exception

      @@ -56,12 +56,12 @@ handler. For example, you can specify the following:

       %exception {
      -    try {
      -        $action
      -    }
      -    catch (RangeError) {
      -        ... handle error ...
      -    }
      +  try {
      +    $action
      +  }
      +  catch (RangeError) {
      +    ... handle error ...
      +  }
       }
       
      @@ -71,13 +71,13 @@ How the exception is handled depends on the target language, for example, Python
       %exception {
      -    try {
      -        $action
      -    }
      -    catch (RangeError) {
      -        PyErr_SetString(PyExc_IndexError,"index out-of-bounds");
      -        SWIG_fail;
      -    }
      +  try {
      +    $action
      +  }
      +  catch (RangeError) {
      +    PyErr_SetString(PyExc_IndexError, "index out-of-bounds");
      +    SWIG_fail;
      +  }
       }
       
      @@ -101,7 +101,7 @@ for exception handling. That directive is deprecated--%exception provides the same functionality, but is substantially more flexible.

      -

      12.1.1 Handling exceptions in C code

      +

      14.1.1 Handling exceptions in C code

      @@ -116,7 +116,7 @@ static char error_message[256]; static int error_status = 0; void throw_exception(char *msg) { - strncpy(error_message,msg,256); + strncpy(error_message, msg, 256); error_status = 1; } @@ -169,7 +169,7 @@ Each target language has its own approach to creating a runtime error/exception and for Perl it is the croak method shown above.

      -

      12.1.2 Exception handling with longjmp()

      +

      14.1.2 Exception handling with longjmp()

      @@ -193,7 +193,7 @@ extern int exception_status; #define try if ((exception_status = setjmp(exception_buffer)) == 0) #define catch(val) else if (exception_status == val) -#define throw(val) longjmp(exception_buffer,val) +#define throw(val) longjmp(exception_buffer, val) #define finally else /* Exception codes */ @@ -245,7 +245,7 @@ Note: This implementation is only intended to illustrate the general idea. To m modify it to handle nested try declarations.

      -

      12.1.3 Handling C++ exceptions

      +

      14.1.3 Handling C++ exceptions

      @@ -280,7 +280,7 @@ class OutOfMemory {};

    -

    12.1.4 Exception handlers for variables

    +

    14.1.4 Exception handlers for variables

    @@ -305,7 +305,7 @@ The %allowexception feature works like any other feature and so can be -

    12.1.5 Defining different exception handlers

    +

    14.1.5 Defining different exception handlers

    @@ -341,12 +341,12 @@ to specific declaration name. For example:

     %exception allocate {
    -    try {
    -        $action
    -    } 
    -    catch (MemoryError) {
    -        croak("Out of memory");
    -    }
    +  try {
    +    $action
    +  }
    +  catch (MemoryError) {
    +    croak("Out of memory");
    +  }
     }
     
    @@ -356,7 +356,7 @@ In this case, the exception handler is only attached to declarations named "allocate". This would include both global and member functions. The names supplied to %exception follow the same rules as for %rename described in the section on -Ambiguity resolution and renaming. +Renaming and ambiguity resolution. For example, if you wanted to define an exception handler for a specific class, you might write this:

    @@ -364,12 +364,12 @@ an exception handler for a specific class, you might write this:
     %exception Object::allocate {
    -    try {
    -        $action
    -    } 
    -    catch (MemoryError) {
    -        croak("Out of memory");
    -    }
    +  try {
    +    $action
    +  }
    +  catch (MemoryError) {
    +    croak("Out of memory");
    +  }
     }
     
    @@ -386,12 +386,12 @@ in the specified class as well as for identically named functions appearing in d
     %exception Object::allocate(int) {
    -    try {
    -        $action
    -    } 
    -    catch (MemoryError) {
    -        croak("Out of memory");
    -    }
    +  try {
    +    $action
    +  }
    +  catch (MemoryError) {
    +    croak("Out of memory");
    +  }
     }
     
    @@ -410,21 +410,21 @@ to attach exceptions to specific parts of a header file. For example: // Define a few exception handlers for specific declarations %exception Object::allocate(int) { - try { - $action - } - catch (MemoryError) { - croak("Out of memory"); - } + try { + $action + } + catch (MemoryError) { + croak("Out of memory"); + } } %exception Object::getitem { - try { - $action - } - catch (RangeError) { - croak("Index out of range"); - } + try { + $action + } + catch (RangeError) { + croak("Index out of range"); + } } ... // Read a raw header file @@ -442,7 +442,7 @@ declarations. However, it never really worked that well and the new %exception directive is much better.

    -

    12.1.6 Special variables for %exception

    +

    14.1.6 Special variables for %exception

    @@ -516,7 +516,7 @@ The special variables are often used in situations where method calls are logged $action } catch (MemoryError) { - croak("Out of memory in $decl"); + croak("Out of memory in $decl"); } } void log(const char *message); @@ -545,7 +545,7 @@ Below shows the expansions for the 1st of the overloaded something wrap -

    12.1.7 Using The SWIG exception library

    +

    14.1.7 Using The SWIG exception library

    @@ -560,17 +560,17 @@ common scripting language exceptions in a portable manner. For example :

    %include exception.i %exception { - try { - $action - } catch(RangeError) { - SWIG_exception(SWIG_ValueError, "Range Error"); - } catch(DivisionByZero) { - SWIG_exception(SWIG_DivisionByZero, "Division by zero"); - } catch(OutOfMemory) { - SWIG_exception(SWIG_MemoryError, "Out of memory"); - } catch(...) { - SWIG_exception(SWIG_RuntimeError,"Unknown exception"); - } + try { + $action + } catch(RangeError) { + SWIG_exception(SWIG_ValueError, "Range Error"); + } catch(DivisionByZero) { + SWIG_exception(SWIG_DivisionByZero, "Division by zero"); + } catch(OutOfMemory) { + SWIG_exception(SWIG_MemoryError, "Out of memory"); + } catch(...) { + SWIG_exception(SWIG_RuntimeError, "Unknown exception"); + } } @@ -600,7 +600,7 @@ SWIG_NullReferenceError The SWIG_exception() function can also be used in typemaps.

    -

    12.2 Object ownership and %newobject

    +

    14.2 Object ownership and %newobject

    @@ -611,8 +611,8 @@ example, consider a function like this:

     Foo *blah() {
    -   Foo *f = new Foo();
    -   return f;
    +  Foo *f = new Foo();
    +  return f;
     }
     
    @@ -645,7 +645,7 @@ you can attach it to class members and parameterized declarations as before. Fo
     %newobject ::blah();                   // Only applies to global blah
    -%newobject Object::blah(int,double);   // Only blah(int,double) in Object
    +%newobject Object::blah(int, double);  // Only blah(int, double) in Object
     %newobject *::copy;                    // Copy method in all classes
     ...
     
    @@ -757,7 +757,7 @@ char *strdup(const char *s); The results might not be what you expect.

    -

    12.3 Features and the %feature directive

    +

    14.3 Features and the %feature directive

    @@ -771,15 +771,15 @@ using the %feature directive. For example:

     %feature("except") Object::allocate {
    -    try {
    -        $action
    -    } 
    -    catch (MemoryError) {
    -        croak("Out of memory");
    -    }
    +  try {
    +    $action
    +  }
    +  catch (MemoryError) {
    +    croak("Out of memory");
    +  }
     }
     
    -%feature("new","1") *::copy;
    +%feature("new", "1") *::copy;
     
    @@ -791,12 +791,12 @@ involving %feature:
     #define %exception %feature("except")
    -#define %newobject %feature("new","1")
    +#define %newobject %feature("new", "1")
     

    -The name matching rules outlined in the Ambiguity resolution and renaming +The name matching rules outlined in the Renaming and ambiguity resolution section applies to all %feature directives. In fact the %rename directive is just a special form of %feature. The matching rules mean that features are very flexible and can be applied with @@ -811,10 +811,10 @@ are defined. For example:

     /* Define a global exception handler */
     %feature("except") {
    -   try {
    -     $action
    -   }
    -   ...
    +  try {
    +    $action
    +  }
    +  ...
     }
     
     ... bunch of declarations ...
    @@ -831,7 +831,7 @@ The following are all equivalent:
     %feature("except") Object::method { $action };
     %feature("except") Object::method %{ $action %};
     %feature("except") Object::method " $action ";
    -%feature("except","$action") Object::method;
    +%feature("except", "$action") Object::method;
     
    @@ -839,7 +839,7 @@ The following are all equivalent: The syntax in the first variation will generate the { } delimiters used whereas the other variations will not.

    -

    12.3.1 Feature attributes

    +

    14.3.1 Feature attributes

    @@ -850,7 +850,7 @@ The following is the generic syntax for features:

    -%feature("name","value", attribute1="AttributeValue1") symbol;
    +%feature("name", "value", attribute1="AttributeValue1") symbol;
     %feature("name", attribute1="AttributeValue1") symbol {value};
     %feature("name", attribute1="AttributeValue1") symbol %{value%};
     %feature("name", attribute1="AttributeValue1") symbol "value";
    @@ -867,11 +867,11 @@ In the following example, MyExceptionClass is the name of the Java clas
     
     %feature("except", throws="MyExceptionClass") Object::method { 
    -   try {
    -     $action
    -   } catch (...) {
    -     ... code to throw a MyExceptionClass Java exception ...
    -   }
    +  try {
    +    $action
    +  } catch (...) {
    +    ... code to throw a MyExceptionClass Java exception ...
    +  }
     };
     
    @@ -880,7 +880,7 @@ In the following example, MyExceptionClass is the name of the Java clas Further details can be obtained from the Java exception handling section.

    -

    12.3.2 Feature flags

    +

    14.3.2 Feature flags

    @@ -914,13 +914,13 @@ int red; // mutable %feature("immutable"); // global enable int orange; // immutable -%feature("immutable","0"); // global disable +%feature("immutable", "0"); // global disable int yellow; // mutable -%feature("immutable","1"); // another form of global enable +%feature("immutable", "1"); // another form of global enable int green; // immutable -%feature("immutable",""); // clears the global feature +%feature("immutable", ""); // clears the global feature int blue; // mutable

    @@ -932,8 +932,8 @@ The above intersperses SWIG directives with C code. Of course you can target fea
    -%feature("immutable","1") orange;
    -%feature("immutable","1") green;
    +%feature("immutable", "1") orange;
    +%feature("immutable", "1") green;
     int red;                        // mutable
     int orange;                     // immutable
     int yellow;                     // mutable
    @@ -949,10 +949,10 @@ The logic above can of course be inverted and rewritten as:
     
     
    -%feature("immutable","1");
    -%feature("immutable","0") red;
    -%feature("immutable","0") yellow;
    -%feature("immutable","0") blue;
    +%feature("immutable", "1");
    +%feature("immutable", "0") red;
    +%feature("immutable", "0") yellow;
    +%feature("immutable", "0") blue;
     int red;                        // mutable
     int orange;                     // immutable
     int yellow;                     // mutable
    @@ -978,12 +978,12 @@ in the swig.swg Library file. The following shows the alternative synta
     The concept of clearing features is discussed next.
     

    -

    12.3.3 Clearing features

    +

    14.3.3 Clearing features

    A feature stays in effect until it is explicitly cleared. A feature is cleared by -supplying a %feature directive with no value. For example %feature("name",""). +supplying a %feature directive with no value. For example %feature("name", ""). A cleared feature means that any feature exactly matching any previously defined feature is no longer used in the name matching rules. So if a feature is cleared, it might mean that another name matching rule will apply. To clarify, let's consider the except feature again (%exception): @@ -993,27 +993,27 @@ To clarify, let's consider the except feature again (%exception // Define global exception handler %feature("except") { - try { - $action - } catch (...) { - croak("Unknown C++ exception"); - } + try { + $action + } catch (...) { + croak("Unknown C++ exception"); + } } // Define exception handler for all clone methods to log the method calls %feature("except") *::clone() { - try { - logger.info("$action"); - $action - } catch (...) { - croak("Unknown C++ exception"); - } + try { + logger.info("$action"); + $action + } catch (...) { + croak("Unknown C++ exception"); + } } ... initial set of class declarations with clone methods ... // clear the previously defined feature -%feature("except","") *::clone(); +%feature("except", "") *::clone(); ... final set of class declarations with clone methods ...

    @@ -1027,8 +1027,8 @@ However, these clone methods will still have an exception handler (without loggi

    Note that clearing a feature is not always the same as disabling it. -Clearing the feature above with %feature("except","") *::clone() is not the same as specifying -%feature("except","0") *::clone(). The former will disable the feature for clone methods - +Clearing the feature above with %feature("except", "") *::clone() is not the same as specifying +%feature("except", "0") *::clone(). The former will disable the feature for clone methods - the feature is still a better match than the global feature. If on the other hand, no global exception handler had been defined at all, then clearing the feature would be the same as disabling it as no other feature would have matched. @@ -1042,7 +1042,7 @@ For example the following attempt to clear the initial feature will not work:

     %feature("except") clone() { logger.info("$action"); $action }
    -%feature("except","") *::clone();
    +%feature("except", "") *::clone();
     
    @@ -1053,7 +1053,7 @@ but this will:
     %feature("except") clone() { logger.info("$action"); $action }
    -%feature("except","") clone();
    +%feature("except", "") clone();
     
    @@ -1066,12 +1066,12 @@ The three macros below show this for the "except" feature:
     #define %exception      %feature("except")
    -#define %noexception    %feature("except","0")
    -#define %clearexception %feature("except","")
    +#define %noexception    %feature("except", "0")
    +#define %clearexception %feature("except", "")
     
    -

    12.3.4 Features and default arguments

    +

    14.3.4 Features and default arguments

    @@ -1146,7 +1146,7 @@ specifying or not specifying default arguments in a feature is not applicable as in SWIG-1.3.23 when the approach to wrapping methods with default arguments was changed.

    -

    12.3.5 Feature example

    +

    14.3.5 Feature example

    @@ -1158,21 +1158,21 @@ in the Python module. You might use %feature to rewrite proxy/shadow cl

     %module example
    -%rename(bar_id) bar(int,double);
    +%rename(bar_id) bar(int, double);
     
     // Rewrite bar() to allow some nice overloading
     
     %feature("shadow") Foo::bar(int) %{
     def bar(*args):
         if len(args) == 3:
    -         return apply(examplec.Foo_bar_id,args)
    -    return apply(examplec.Foo_bar,args)
    +        return apply(examplec.Foo_bar_id, args)
    +    return apply(examplec.Foo_bar, args)
     %}
         
     class Foo {
     public:
    -    int bar(int x);
    -    int bar(int x, double y);
    +  int bar(int x);
    +  int bar(int x, double y);
     }
     
    diff --git a/Doc/Manual/D.html b/Doc/Manual/D.html index 9e8e65358..d97267a5b 100644 --- a/Doc/Manual/D.html +++ b/Doc/Manual/D.html @@ -6,7 +6,7 @@ -

    22 SWIG and D

    +

    23 SWIG and D

      @@ -41,7 +41,7 @@ -

      22.1 Introduction

      +

      23.1 Introduction

      From the D Programming Language web site: D is a systems programming language. Its focus is on combining the power and high performance of C and C++ with the programmer productivity of modern languages like Ruby and Python. [...] The D language is statically typed and compiles directly to machine code. As such, it is not very surprising that D is able to directly interface with C libraries. Why would a SWIG module for D be needed then in the first place?

      @@ -53,10 +53,10 @@

      To help addressing these issues, the SWIG C# module has been forked to support D. Is has evolved quite a lot since then, but there are still many similarities, so if you do not find what you are looking for on this page, it might be worth having a look at the chapter on C# (and also on Java, since the C# module was in turn forked from it).

      -

      22.2 Command line invocation

      +

      23.2 Command line invocation

      -

      To activate the D module, pass the -d option to SWIG at the command line. The same standard command line switches as with any other language module are available, plus the following D specific ones:

      +

      To activate the D module, pass the -d option to SWIG at the command line. The same standard command line options as with any other language module are available, plus the following D specific ones:

      -d2
      @@ -66,8 +66,8 @@
      -splitproxy
      -

      By default, SWIG generates two D modules: the proxy module, named like the source module (either specified via the %module directive or via the module command line switch), which contains all the proxy classes, functions, enums, etc., and the intermediary module (named like the proxy module, but suffixed with _im), which contains all the extern(C) function declarations and other private parts only used internally by the proxy module.

      -

      If the split proxy mode is enabled by passing this switch at the command line, all proxy classes and enums are emitted to their own D module instead. The main proxy module only contains free functions and constants in this case.

      +

      By default, SWIG generates two D modules: the proxy module, named like the source module (either specified via the %module directive or via the module command line option), which contains all the proxy classes, functions, enums, etc., and the intermediary module (named like the proxy module, but suffixed with _im), which contains all the extern(C) function declarations and other private parts only used internally by the proxy module.

      +

      If the split proxy mode is enabled by passing this option at the command line, all proxy classes and enums are emitted to their own D module instead. The main proxy module only contains free functions and constants in this case.

      -package <pkg>
      @@ -77,16 +77,16 @@
      -wrapperlibrary <wl>
      -

      The code SWIG generates to dynamically load the C/C++ wrapper layer looks for a library called $module_wrap by default. With this switch, you can override the name of the file the wrapper code loads at runtime (the lib prefix and the suffix for shared libraries are appended automatically, depending on the OS).

      +

      The code SWIG generates to dynamically load the C/C++ wrapper layer looks for a library called $module_wrap by default. With this option, you can override the name of the file the wrapper code loads at runtime (the lib prefix and the suffix for shared libraries are appended automatically, depending on the OS).

      This might especially be useful if you want to invoke SWIG several times on separate modules, but compile the resulting code into a single shared library.

      -

      22.3 Typemaps

      +

      23.3 Typemaps

      -

      22.3.1 C# <-> D name comparison

      +

      23.3.1 C# <-> D name comparison

      If you already know the SWIG C# module, you might find the following name comparison table useful:

      @@ -107,12 +107,12 @@ csimports <-> dimports csbody <-> dbody csfinalize <-> ddestructor - csdestruct <-> ddispose - csdestruct_derived <-> ddispose_derived + csdisposing <-> ddispose + csdisposing_derived <-> ddispose_derived
    -

    22.3.2 ctype, imtype, dtype

    +

    23.3.2 ctype, imtype, dtype

    Mapping of types between the C/C++ library, the C/C++ library wrapper exposing the C functions, the D wrapper module importing these functions and the D proxy code.

    @@ -120,7 +120,7 @@

    The ctype typemap is used to determine the types to use in the C wrapper functions. The types from the imtype typemap are used in the extern(C) declarations of these functions in the intermediary D module. The dtype typemap contains the D types used in the D proxy module/class.

    -

    22.3.3 in, out, directorin, directorout

    +

    23.3.3 in, out, directorin, directorout

    Used for converting between the types for C/C++ and D when generating the code for the wrapper functions (on the C++ side).

    @@ -130,7 +130,7 @@

    The directorin typemap is used to convert parameters to the type used in the D director callback function, its return value is processed by directorout (see below).

    -

    22.3.4 din, dout, ddirectorin, ddirectorout

    +

    23.3.4 din, dout, ddirectorin, ddirectorout

    Typemaps for code generation in D proxy and type wrapper classes.

    @@ -157,13 +157,13 @@ dtype DClass.method(dtype a) -

    22.3.5 typecheck typemaps

    +

    23.3.5 typecheck typemaps

    Because, unlike many scripting languages supported by SWIG, D does not need any dynamic dispatch helper to access an overloaded function, the purpose of these is merely to issue a warning for overloaded C++ functions that cannot be overloaded in D (as more than one C++ type maps to a single D type).

    -

    22.3.6 Code injection typemaps

    +

    23.3.6 Code injection typemaps

    These typemaps are used for generating the skeleton of proxy classes for C++ types.

    @@ -174,8 +174,11 @@

    dconstructor, ddestructor, ddispose and ddispose_derived are used to generate the class constructor, destructor and dispose() method, respectively. The auxiliary code for handling the pointer to the C++ object is stored in dbody and dbody_derived. You can override them for specific types.

    +

    +Code can also be injected into the D proxy class using %proxycode. +

    -

    22.3.7 Special variable macros

    +

    23.3.7 Special variable macros

    The standard SWIG special variables are available for use within typemaps as described in the Typemaps documentation, for example $1, $input, $result etc.

    @@ -229,8 +232,9 @@ void foo(SomeClass arg) { %newobject bar(); SomeClass *bar(); -%} -

    The code generated for foo() and bar() looks like this:

    +%} + +

    The code generated for foo() and bar() looks like this:

     SomeClass foo() {
       return new SomeClass(example_im.foo(), false);
    @@ -276,7 +280,7 @@ class SomeClass : AnInterface, AnotherInterface {
       ...
     }
     
    -

    For this to work, AnInterface and AnotherInterface have to be in scope. If SWIG is not in split proxy mode, this is already the case, but it it is, they have to be added to the import list via the dimports typemap. Additionally, the import statement depends on the package SWIG is configured to emit the modules to.

    +

    For this to work, AnInterface and AnotherInterface have to be in scope. If SWIG is not in split proxy mode, this is already the case, but if it is, they have to be added to the import list via the dimports typemap. Additionally, the import statement depends on the package SWIG is configured to emit the modules to.

    The $importtype macro helps you to elegantly solve this problem:

     %typemap(dimports) RemoteMpe %{
    @@ -295,7 +299,7 @@ $importtype(AnotherInterface)
     
     
     
    -

    22.4 D and %feature

    +

    23.4 D and %feature

    The D module defines a number of directives which modify the SWIG features set globally or for a specific declaration:

    @@ -325,7 +329,7 @@ struct A { -

    22.5 Pragmas

    +

    23.5 Pragmas

    There are a few SWIG pragmas specific to the D module, which you can use to influence the D code SWIG generates:

    @@ -364,7 +368,7 @@ struct A { -

    22.6 D Exceptions

    +

    23.6 D Exceptions

    Out of the box, C++ exceptions are fundamentally incompatible to their equivalent in the D world and cannot simply be propagated to a calling D method. There is, however, an easy way to solve this problem: Just catch the exception in the C/C++ wrapper layer, pass the contents to D, and make the wrapper code rethrow the exception in the D world.

    @@ -374,7 +378,7 @@ struct A {

    As this feature is implemented in exactly the same way it is for C#, please see the C# documentation for a more detailed explanation.

    -

    22.7 D Directors

    +

    23.7 D Directors

    When the directors feature is activated, SWIG generates extra code on both the C++ and the D side to enable cross-language polymorphism. Essentially, this means that if you subclass a proxy class in D, C++ code can access any overridden virtual methods just as if you created a derived class in C++.

    @@ -383,16 +387,16 @@ struct A {

    -

    22.8 Other features

    +

    23.8 Other features

    -

    22.8.1 Extended namespace support (nspace)

    +

    23.8.1 Extended namespace support (nspace)

    By default, SWIG flattens all C++ namespaces into a single target language namespace, but as for Java and C#, the nspace feature is supported for D. If it is active, C++ namespaces are mapped to D packages/modules. Note, however, that like for the other languages, free variables and functions are not supported yet; currently, they are all allows written to the main proxy D module.

    -

    22.8.2 Native pointer support

    +

    23.8.2 Native pointer support

    Contrary to many of the scripting languages supported by SWIG, D fully supports C-style pointers. The D module thus includes a custom mechanism to wrap C pointers directly as D pointers where applicable, that is, if the type that is pointed to is represented the same in C and D (on the bit-level), dubbed a primitive type below.

    @@ -404,7 +408,7 @@ struct A {

    To determine if a type should be considered primitive, the cprimitive attribute on its dtype attribute is used. For example, the dtype typemap for float has cprimitive="1", so the code from the nativepointer attribute is taken into account e.g. for float ** or the function pointer float (*)(float *).

    -

    22.8.3 Operator overloading

    +

    23.8.3 Operator overloading

    The D module comes with basic operator overloading support for both D1 and D2. There are, however, a few limitations arising from conceptual differences between C++ and D:

    @@ -416,22 +420,22 @@ struct A {

    There are also some cases where the operators can be translated to D, but the differences in the implementation details are big enough that a rather involved scheme would be required for automatic wrapping them, which has not been implemented yet. This affects, for example, the array subscript operator, [], in combination with assignments - while operator [] in C++ simply returns a reference which is then written to, D resorts to a separate opIndexAssign method -, or implicit casting (which was introduced in D2 via alias this). Despite the lack of automatic support, manually handling these cases should be perfectly possible.

    -

    22.8.4 Running the test-suite

    +

    23.8.4 Running the test-suite

    As with any other language, the SWIG test-suite can be built for D using the *-d-test-suite targets of the top-level Makefile. By default, D1 is targeted, to build it with D2, use the optional D_VERSION variable, e.g. make check-d-test-suite D_VERSION=2.

    -

    Note: If you want to use GDC on Linux or another platform which requires you to link libdl for dynamically loading the shared library, you might have to add -ldl manually to the d_compile target in Examples/Makefile, because GDC does not currently honor the pragma(lib,...) statement.

    +

    Note: If you want to use GDC on Linux or another platform which requires you to link libdl for dynamically loading the shared library, you might have to add -ldl manually to the d_compile target in Examples/Makefile, because GDC does not currently honor the pragma(lib, ...) statement.

    -

    22.9 D Typemap examples

    +

    23.9 D Typemap examples

    There are no D-specific typemap examples yet. However, with the above name comparison table, you should be able to get an idea what can be done by looking at the corresponding C# section.

    -

    22.10 Work in progress and planned features

    +

    23.10 Work in progress and planned features

    There are a couple of features which are not implemented yet, but would be very useful and might be added in the near future:

    diff --git a/Doc/Manual/Doxygen.html b/Doc/Manual/Doxygen.html new file mode 100644 index 000000000..ff025c047 --- /dev/null +++ b/Doc/Manual/Doxygen.html @@ -0,0 +1,1838 @@ + + + +SWIG and Doxygen Translation + + + +

    17 SWIG and Doxygen Translation

    + + + + + + +

    +This chapter describes SWIG's support for translating Doxygen comments +found in interface and header files into a target language's normal +documentation language. Currently only Javadoc and Pydoc is +supported. +

    + +

    17.1 Doxygen translation overview

    + + +

    +The Doxygen Translation module of SWIG adds an extra layer of +functionality to SWIG, allowing automated translation of Doxygen formatted comments +from input files into a documentation language more suited for the +target language. Currently this module only translates into Javadoc +and Pydoc for the SWIG Java and Python modules. +Other extensions could be added at a later date. +The Doxygen Translation module originally started as +a Google Summer of +Code proposal from Summer 2008. +

    + +

    17.2 Preparations

    + + +

    +To make use of the comment translation system, your documentation +comments must be in properly formatted Doxygen. Doxygen comments can be +present in your main SWIG interface file or any header file that it +imports. You are advised to be validate that your comments compile +properly with Doxygen before you try to translate them. Doxygen +itself is a more comprehensive tool and can provide you better feedback for +correcting any syntax errors that may be present. Please look at +Doxygen's Documenting the +code for the full comment format specifications. However, SWIG's +Doxygen parser will still report many errors and warnings found +in comments (like unterminated strings or missing ending tags). +

    + +

    +Currently, the whole subset of Doxygen comment styles is supported +(See +Documenting the code). Here they are: +

    + +
    +/**
    + * Javadoc style comment, multiline
    + */
    +/*!
    + * QT-style comment, multiline
    + */
    +/**
    + Any of the above, but without intermediate *'s
    + */
    +/// Single-line comment
    +//! Another single-line comment
    +
    + +

    +Also any of the above with '<' added after comment-starting symbol, +like /**<, /*!<, ///<, or //!< will be +treated as a post-comment and will be assigned to the code before the +comment. + +Any number of '*' or '/' within a Doxygen comment is considered to be a +separator and is not included in the final comment, so you may safely use +comments like /*********/ or //////////. +

    + +

    +Please note, as SWIG parses the input file by itself with strict grammar, +there is only a limited support for various cases of comment placement +in the file. +

    +

    +Comments can be placed before C/C++ expressions on separate lines: +

    + +
    +/**
    + * Some comment
    + */
    +void someOtherFunction();
    +/**
    + * Some comment
    + */
    +void someFunction();
    +
    +class Shape {
    +  /*
    +   * Calculate the area in cm^2
    +   */
    +  int getArea();
    +}
    +
    + +

    +After C/C++ expressions at the end of the line: +

    + +
    +int someVariable = 9; ///< This is a var holding magic number 9
    +void doNothing(); ///< This does nothing, nop
    +
    + +

    +and in some special cases, like function parameter comments: +

    + +
    +void someFunction(
    +         int a ///< Some parameter 
    +     );
    +
    + +

    +or enum element comments: +

    + +
    +enum E_NUMBERS
    +{
    +    EN_ZERO, ///< The first enum item, gets zero as it's value
    +    EN_ONE, ///< The second, EN_ONE=1
    +    EN_THREE
    +};
    +
    + +

    +Currently only comments directly before or after the code items +are supported. Doxygen also supports comments containing structural commands, +where the comments for a code item are not put directly before or after the code item. +These structural commands are stripped out by SWIG and are not assigned to anything. +

    + +

    17.2.1 Enabling Doxygen translation

    + + +

    +Doxygen comments translation is disabled by default and needs to be explicitly +enabled using the command line -doxygen option for the languages that +do support it (currently Java and Python). +

    + +

    17.2.2 Doxygen-specific %feature directives

    + + +

    +Translation of Doxygen comments is influenced by the following %feature directives: +

    + +

    17.2.2.1 doxygen:notranslate

    + + +

    +Turns off translation of Doxygen comments to the target language syntax: the +original comment will be copied to the output unchanged. This is useful if you +want to use Doxygen itself to generate documentation for the target language +instead of the corresponding language tool (javadoc, sphinx, +...). +

    + + +

    17.2.2.2 doxygen:alias:<command-name>

    + + +

    +Specify an alias for a Doxygen command with the given name. This can be useful +for custom Doxygen commands which can be defined using ALIASES option +for Doxygen itself but which are unknown to SWIG. "command-name" is the +name of the command in the Doxyfile, e.g. if it contains +

    + +
    +ALIASES = "sideeffect=\par Side Effects:\n"
    +
    + +

    +Then you could also specify the same expansion for SWIG with: +

    + +
    +%feature("doxygen:alias:sideeffect") "\par Side Effects:\n"
    +
    + +

    +Please note that command arguments are not currently supported with this +feature. +

    + +

    +Notice that it is perfectly possible and potentially useful to define the alias +expansion differently depending on the target language, e.g. with +

    + +
    +#ifdef SWIGJAVA
    +%feature("doxygen:alias:not_for_java") "This functionality is not available for Java"
    +#else
    +%feature("doxygen:alias:not_for_java") ""
    +#endif
    +
    + +

    +you could use @not_for_java in the documentation comments of all +functions which can't, for whatever reason, be currently exposed in Java +wrappers of the C++ API. +

    + + +

    17.2.2.3 doxygen:ignore:<command-name>

    + + +

    +This feature makes it possible to just ignore an unknown Doxygen command, instead of +replacing it with the predefined text that doxygen:alias does. +For example, you could use +

    + +
    +%feature("doxygen:ignore:transferfull") Fantastic();
    +/**
    +    A fantastic function.
    +
    +    @transferfull Command ignored, but anything here is still included.
    + */
    +int * Fantastic();
    +
    + +

    +if you use a custom Doxygen transferfull command to indicate that the +return value ownership is transferred to the caller, as this information doesn't +make much sense for the other languages without explicit ownership management. +

    + +

    +Doxygen syntax is rather rich and, in addition to simple commands such as +@transferfull, it is also possible to define commands with arguments. +As explained in Doxygen documentation, +the arguments can have a range of a single word, everything until the end of +line or everything until the end of the next paragraph. Currently, only the "end +of line" case is supported using the range="line" argument of the +feature directive: +

    + +
    +// Ignore occurrences of
    +//
    +//    @compileroptions Some special C++ compiler options.
    +//
    +// in Doxygen comments as C++ options are not interesting for the target language
    +// developers.
    +%feature("doxygen:ignore:compileroptions", range="line") Amazing();
    +
    +/**
    +    An amazing function.
    +
    +    @compileroptions This function must be compiled with /EHa when using MSVC.
    + */
    +void Amazing();
    +
    +
    + +

    +In addition, it is also possible to have custom pairs of begin/end tags, +similarly to the standard Doxygen @code/@endcode, for example. Such +tags can also be ignored using the special value of range starting with +end to indicate that the range is an interval, for example: +

    + +
    +%feature("doxygen:ignore:forcpponly", range="end"); // same as "end:endforcpponly"
    +/**
    +    An incredible function.
    +
    +    @forcpponly
    +    This is C++-specific.
    +    @endforcpponly
    + */
    +void Incredible();
    +
    + +

    +would ignore everything between @forcpponly and @endforcpponly +commands in Doxygen comments. By default, the name of the end command is the +same as of the start one with "end" prefix, following Doxygen conventions, but +this can be overridden by providing the end command name after the colon. +

    +

    +This example shows how custom tags can be used to bracket anything specific to +C++ and prevent it from appearing in the target language documentation. +Conversely, another pair of custom tags could be used to put target language +specific information in the C++ comments. In this case, only the custom tags +themselves should be ignored, but their contents should be parsed as usual and +contents="parse" can be used for this: +

    + +
    +%feature("doxygen:ignore:beginPythonOnly", range="end:endPythonOnly", contents="parse");
    +/**
    +    A splendid function.
    +
    +    @beginPythonOnly
    +    This is specific to @b Python.
    +    @endPythonOnly
    + */
    +void Splendid();
    +
    +
    + +

    +Putting everything together, if these directives are in effect: +

    + +
    +%feature("doxygen:ignore:transferfull");
    +%feature("doxygen:ignore:compileroptions", range="line");
    +%feature("doxygen:ignore:forcpponly", range="end");
    +%feature("doxygen:ignore:beginPythonOnly", range="end:endPythonOnly", contents="parse");
    +
    + +

    +then the following C++ Doxygen comment: +

    + +
    +/**
    +    A contrived example of ignoring too many commands in one comment.
    +
    +    @forcpponly
    +    This is C++-specific.
    +    @endforcpponly
    +
    +    @beginPythonOnly
    +    This is specific to @b Python.
    +    @endPythonOnly
    +
    +    @transferfull Command ignored, but anything here is still included.
    +
    +    @compileroptions This function must be compiled with /EHa when using MSVC.
    + */
    +int * Contrived();
    +
    + +

    +would be translated to this comment in Python: +

    + +
    +def func():
    +    r"""
    +    A contrived example of ignoring too many commands in one comment.
    +
    +    This is specific to **Python**.
    +
    +    Command ignored, but anything here is still included.
    +    """
    +    ...
    +
    + + +

    17.2.2.4 doxygen:nolinktranslate

    + + +

    +Turn off automatic link-objects translation. +This is only applicable to Java at the moment. +

    + + +

    17.2.2.5 doxygen:nostripparams

    + + +

    +Turn off stripping of @param and @tparam +Doxygen commands if the parameter is not found in the function signature. +This is only applicable to Java at the moment. +

    + + +

    17.2.3 Additional command line options

    + + +

    +ALSO TO BE ADDED (Javadoc auto brief?) +

    + +

    17.3 Doxygen to Javadoc

    + + +

    +If translation is enabled, Javadoc formatted comments should be +automatically placed in the correct locations in the resulting module +and proxy files. +

    + +

    17.3.1 Basic example

    + + +

    +Here is an example segment from an included header file +

    +
    +/*! This is describing class Shape
    + \author Bob
    + */
    +
    +class Shape {
    +public:
    +  Shape() {
    +    nshapes++;
    +  }
    +  virtual ~Shape() {
    +    nshapes--;
    +  };
    +  double  x, y; /*!< Important Variables */
    +  void    move(double dx, double dy); /*!< Moves the Shape */
    +  virtual double area(void) = 0; /*!< \return the area */
    +  virtual double perimeter(void) = 0; /*!< \return the perimeter */
    +  static  int nshapes;
    +};
    +
    + +

    +Simply running SWIG should result in the following code being present in Shapes.java +

    + +
    +
    +/**
    + * This is describing class Shape 
    + * @author Bob 
    + * 
    + */
    +
    +public class Shape {
    +
    +...
    +
    +/**
    + * Important Variables 
    + */
    +  public void setX(double value) {
    +    ShapesJNI.Shape_x_set(swigCPtr, this, value);
    +  }
    +
    +/**
    + * Important Variables 
    + */
    +  public double getX() {
    +    return ShapesJNI.Shape_x_get(swigCPtr, this);
    +  }
    +
    +/**
    + * Moves the Shape 
    + */
    +  public void move(double dx, double dy) {
    +    ShapesJNI.Shape_move(swigCPtr, this, dx, dy);
    +  }
    +
    +/**
    + * @return the area 
    + */
    +  public double area() {
    +    return ShapesJNI.Shape_area(swigCPtr, this);
    +  }
    +
    +/**
    + * @return the perimeter 
    + */
    +  public double perimeter() {
    +    return ShapesJNI.Shape_perimeter(swigCPtr, this);
    +  }
    +}
    +
    +
    + +

    +The code Java-wise should be identical to what would have been +generated without the doxygen functionality enabled. When the Doxygen Translator +module encounters a comment that contains nothing useful or a doxygen comment that it cannot +parse, it will not affect the functionality of the SWIG generated +code. +

    + +

    +The Javadoc translator will handle most of the tags conversions (see the +table below). It will also automatically translate link-objects +params, in \see and \link...\endlink commands. For example, +'someFunction(std::string)' will be converted to +'someFunction(String)'. If +you don't want such behaviour, you could turn this off by using the +'doxygen:nolinktranslate' feature. Also all '\param' and '\tparam' +commands are stripped out, if the specified parameter is not present in +the function. Use 'doxygen:nostripparams' to avoid. +

    + +

    +Javadoc translator features summary +(see %feature +directives): +

    + +

    17.3.2 Javadoc tags

    + + +

    +Here is the list of all Doxygen tags and the description of how they are translated to Javadoc +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Doxygen tags
    \awrapped with <i> html tag
    \argwrapped with <li> html tag
    \authortranslated to @author
    \authorstranslated to @author
    \bwrapped with <b> html tag
    \cwrapped with <code> html tag
    \citewrapped with <i> html tag
    \codetranslated to {@code ...}
    \condtranslated to 'Conditional comment: <condition>'
    \copyrightreplaced with 'Copyright:'
    \deprecatedtranslated to @deprecated
    \ewrapped with <i> html tag
    \elsereplaced with '}Else:{'
    \elseifreplaced with '}Else if: <condition>{'
    \emwrapped with <i> html tag
    \endcodesee note for \code
    \endcondreplaced with 'End of conditional comment.'
    \endifreplaced with '}'
    \endlinksee note for \link
    \endverbatimsee note for \verbatim
    \exceptiontranslated to @exception
    \f$, \f[, \f], \f{, \f}LateX formulas are left unchanged
    \ifreplaced with 'If: <condition> {'
    \ifnotreplaced with 'If not: <condition> {'
    \imagetranslated to <img/> html tag only if target=HTML
    \liwrapped with <li> html tag
    \linktranslated to {@link ...}
    \nreplaced with new line char
    \notereplaced with 'Note:'
    \overloadprints 'This is an overloaded ...' according to Doxygen docs
    \pwrapped with <code> html tag
    \parreplaced with <p alt='title'>...</p>
    \paramtranslated to @param
    \remarkreplaced with 'Remarks:'
    \remarksreplaced with 'Remarks:'
    \resulttranslated to @return
    \returntranslated to @return
    \returnstranslated to @return
    \satranslated to @see
    \seetranslated to @see
    \sincetranslated to @since
    \throwtranslated to @throws
    \throwstranslated to @throws
    \todoreplaced with 'TODO:'
    \tparamtranslated to @param
    \verbatimtranslated to {@literal ...}
    \versiontranslated to @version
    \warningtranslated to 'Warning:'
    \$prints $ char
    \@prints @ char
    \\prints \ char
    \&prints & char
    \~prints ~ char
    \<prints < char
    \>prints > char
    \#prints # char
    \%prints % char
    \"prints " char
    \.prints . char
    \::prints ::
    +
    + +

    17.3.3 Unsupported tags

    + + +

    +Doxygen has a wealth of tags such as @latexonly that have no +equivalent in Javadoc (all supported tags are listed in +Javadoc documentation). +As a result several tags have no +translation or particular use, such as some linking and section tags. +These are suppressed with their content just printed out (if the tag has any +sense, typically text content). +Here is the list of these tags: +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Unsupported Doxygen tags
    \addindex\addtogroup\anchor\attention
    \brief\bug\callgraph\callergraph
    \class\copybrief\copydetails\copydoc
    \date\def\defgroup\details
    \dir\dontinclude\dot\dotfile
    \enddot\endhtmlonly\endinternal\endlatexonly
    \endmanonly\endmsc\endrtfonly\endxmlonly
    \enum\example\extends
    \file\fn\headerfile\hideinitializer
    \htmlinclude\htmlonly\implements\include
    \includelineno\ingroup\internal\invariant
    \interface\latexonly\line\mainpage
    \manonly\memberof\msc\mscfile
    \name\namespace\nosubgrouping\package
    \page\paragraph\post\pre
    \private\privatesection\property\protected
    \protectedsection\protocol\public\publicsection
    \ref\related\relates\relatedalso
    \relatesalso\retval\rtfonly\section
    \short\showinitializer\skip\skipline
    \snippet\struct\subpage\subsection
    \subsubsection\tableofcontents\test\typedef
    \union\until\var\verbinclude
    \weakgroup\xmlonly\xrefitem\category
    +
    + +

    + +If one of the following Doxygen tags appears as the first tag in a +comment, the whole comment block is ignored: + + +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Ignored Doxygen tags
    \addtogroup\callgraph\callergraph\category
    \class\def\defgroup\dir
    \enum\example\file\fn
    \headerfile\hideinitializer\interface\internal
    \mainpage\name\namespace\nosubgrouping
    \overload\package\page\property
    \protocol\relates\relatesalso\showinitializer
    \struct\name\namespace\nosubgrouping
    \typedef\union\var\weakgroup
    +
    + + + +

    17.3.4 Further details

    + + +

    +TO BE ADDED. +

    + +

    17.4 Doxygen to Pydoc

    + + +

    +If translation is enabled, Pydoc formatted comments should be +automatically placed in the correct locations in the resulting module +and proxy files. The problem is that Pydoc has no tag mechanism like +Doxygen or Javadoc, so most of Doxygen commands are translated by merely +copying the appropriate command text. +

    + +

    17.4.1 Basic example

    + + +

    +Here is an example segment from an included header file +

    +
    +/*! This is describing class Shape
    + \author Bob
    + */
    +
    +class Shape {
    +public:
    +  Shape() {
    +    nshapes++;
    +  }
    +  virtual ~Shape() {
    +    nshapes--;
    +  };
    +  double  x, y; /*!< Important Variables */
    +  void    move(double dx, double dy); /*!< Moves the Shape */
    +  virtual double area(void) = 0; /*!< \return the area */
    +  virtual double perimeter(void) = 0; /*!< \return the perimeter */
    +  static  int nshapes;
    +};
    +
    + +

    +Simply running SWIG should result in the following code being present in Shapes.py +

    + +
    +
    +...
    +
    +class Shape(_object):
    +    """
    +    This is describing class Shape 
    +    Authors:
    +    Bob 
    +
    +    """
    +    
    +    ...
    +    
    +    def move(self, *args):
    +        """
    +        Moves the Shape 
    +        """
    +        return _Shapes.Shape_move(self, *args)
    +
    +    def area(self):
    +        """
    +        Return:
    +        the area 
    +        """
    +        return _Shapes.Shape_area(self)
    +
    +    def perimeter(self):
    +        """
    +        Return:
    +        the perimeter 
    +        """
    +        return _Shapes.Shape_perimeter(self)
    +
    + +

    +If any parameters of a function or a method are documented in the Doxygen comment, +their description is copied into the generated output using +Sphinx documentation conventions. For example +

    +
    +/**
    +    Set a breakpoint at the given location.
    +
    +    @param filename The full path to the file.
    +    @param line_number The line number in the file.
    + */
    +bool SetBreakpoint(const char* filename, int line_number);
    +
    + +

    +would be translated to +

    + +
    +def SetBreakpoint(filename, line_number):
    +    r"""
    +    Set a breakpoint at the given location.
    +
    +    :type filename: string
    +    :param filename: The full path to the file.
    +    :type line_number: int
    +    :param line_number: The line number in the file.
    +    """
    +
    +

    +The types used for the parameter documentation come from the "doctype" typemap which +is defined for all the primitive types and a few others (e.g. std::string and +shared_ptr<T>) but for non-primitive types is taken to be just the C++ +name of the type with namespace scope delimiters (::) replaced with a dot. To +change this, you can define your own typemaps for the custom types, e.g: +

    +
    +%typemap(doctype) MyDate "datetime.date";
    +
    + +

    +Currently Doxygen comments assigned to global variables and static member variables +are not present in generated code, so they have no comment translated for them. +

    + +

    + Whitespace and tables + Whitespace is preserved when translating comments, so it makes + sense to have Doxygen comments formatted in a readable way. This + includes tables, where tags <th>, <td> and </tr>are translated + to '|'. The line after line with <th> tags contains dashes. + If we take care about whitespace, comments in Python are much more + readable. Example: + +

    +/**
    + * <table border = '1'>
    + * <caption>Animals</caption>
    + * <tr><th> Column 1 </th><th> Column 2 </th></tr>
    + * <tr><td> cow      </td><td> dog      </td></tr>
    + * <tr><td> cat      </td><td> mouse    </td></tr>
    + * <tr><td> horse    </td><td> parrot   </td></tr>
    + * </table>
    + */
    +
    +

    +translates to Python as: +

    +
    +  Animals
    +  | Column 1 | Column 2 |
    +  -----------------------
    +  | cow      | dog      |
    +  | cat      | mouse    |
    +  | horse    | parrot   |
    +
    + +

    + Overloaded functions +Since all the overloaded functions in c++ are wrapped into one Python +function, Pydoc translator will combine every comment of every +overloaded function and put it into the comment for the one wrapper function. +

    +

    +If you intend to use resulting generated Python file with the Doxygen docs +generator, rather than Pydoc, you may want to turn off translation +completely (doxygen:notranslate feature). Then SWIG will just copy +the comments to the proxy file and reformat them if needed, but all +the comment content will be left as is. As Doxygen doesn't support +special commands in Python comments +(see Doxygen +docs), you may want to use some tool like doxypy +(doxypy) +to do the work. +

    + +

    17.4.2 Pydoc translator

    + + +

    +Here is the list of all Doxygen tags and the description of how they are translated to Pydoc +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Doxygen tags
    \awrapped with '_'
    \argprepended with ' --'
    \authorprints 'Author:'
    \authorsprints 'Author:'
    \bwrapped with '__'
    \citewrapped with single quotes
    \condtranslated to 'Conditional comment: <condition>'
    \copyrightprints 'Copyright:'
    \deprecatedprints 'Deprecated:'
    \ewrapped with '_'
    \elsereplaced with '}Else:{'
    \elseifreplaced with '}Else if: <condition>{'
    \emwrapped with '_'
    \endcondreplaced with 'End of conditional comment.'
    \endifreplaced with '}'
    \exceptionreplaced with 'Throws:'
    \ifreplaced with 'If: <condition> {'
    \ifnotreplaced with 'If not: <condition> {'
    \liprepended with ' --'
    \nreplaced with new line char
    \notereplaced with 'Note:'
    \overloadprints 'This is an overloaded ...' according to Doxygen docs
    \parreplaced with 'Title: ...'
    \paramtranslated to 'Arguments:\n param(type) --description'
    \remarkreplaced with 'Remarks:'
    \remarksreplaced with 'Remarks:'
    \resultreplaced with 'Result:'
    \returnreplaced with 'Result:'
    \returnsreplaced with 'Result:'
    \sareplaced with 'See also:'
    \seereplaced with 'See also:'
    \sincereplaced with 'Since:'
    \throwreplaced with 'Throws:'
    \throwsreplaced wih 'Throws:'
    \todoreplaced with 'TODO:'
    \tparamtranslated to 'Arguments:\n param(type) --description'
    \versionreplaced with 'Version:'
    \warningtranslated to 'Warning:'
    \$prints $ char
    \@prints @ char
    \\prints \ char
    \&prints & char
    \~prints ~ char
    \<prints < char
    \>prints > char
    \#prints # char
    \%prints % char
    \"prints " char
    \.prints . character
    \::prints ::
    +
    + +

    17.4.3 Unsupported tags

    + + +

    +Doxygen has a wealth of tags such as @latexonly that have no +equivalent in Pydoc. As a result several tags that have no +translation (or particular use, such as some linking and section tags) +are suppressed with their content just printed out (if it has any +sense, typically text content). +Here is the list of these tags: +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Unsupported Doxygen tags
    \addindex\addtogroup\anchor\attention
    \brief\bug\callgraph\callergraph
    \class\copybrief\copydetails\copydoc
    \date\def\defgroup\details
    \dir\dontinclude\dot\dotfile
    \code\endcode\endverbatim\endlink
    \enddot\endhtmlonly\endinternal\endlatexonly
    \endmanonly\endmsc\endrtfonly\endxmlonly
    \enum\example\extends\f$
    \f[\f]\f{\f}
    \file\fn\headerfile\hideinitializer
    \htmlinclude\htmlonly\implements\include
    \image\link\verbatim\p
    \includelineno\ingroup\internal\invariant
    \interface\latexonly\line\mainpage
    \manonly\memberof\msc\mscfile
    \name\namespace\nosubgrouping\package
    \page\paragraph\post\pre
    \private\privatesection\property\protected
    \protectedsection\protocol\public\publicsection
    \ref\related\relates\relatedalso
    \relatesalso\retval\rtfonly\section
    \short\showinitializer\skip\skipline
    \snippet\struct\subpage\subsection
    \subsubsection\tableofcontents\test\typedef
    \union\until\var\verbinclude
    \weakgroup\xmlonly\xrefitem\category
    \c
    +
    + +

    17.4.4 Further details

    + + +

    +TO BE ADDED. +

    + +

    17.5 Troubleshooting

    + + +

    +When running SWIG with command line option -doxygen, it may happen +that SWIG will fail to parse the code, which is valid C++ code and +is parsed without problems without the option. The problem is, +that Doxygen comments are not tokens (the C/C++ compiler actually never +sees them) and that they can appear anywhere in the code. That's why it is +practically impossible to handle all corner cases with the parser. +However, these problems can usually be avoided by minor changes in the +code or comment. Known problems and solutions are shown in this section. +

    + + +

    +Recommended approach is to first run SWIG without command line +option -doxygen. When it successfully processes the code, +include the option and fix problems with Doxygen comments. +

    + + +

    17.5.1 Problem with conditional compilation

    + + +

    + Inserting a conditional compilation preprocessor directive between a + Doxygen comment and a commented item may break parsing: +

    + + +
    +class A {
    +  /**
    +   * Some func.
    +   */
    +  #ifndef SWIG
    +  void myfunc()
    +  {
    +  }
    +  #endif
    +};
    +
    + +

    + The solution is to move the directive above the comment: +

    + +
    +class A {
    +  #ifndef SWIG
    +  /**
    +   * Some func.
    +   */
    +  void myfunc()
    +  {
    +  }
    +  #endif
    +};
    +
    + + +

    17.6 Developer information

    + + +

    +This section contains information for developers enhancing the Doxygen translator. +

    + +

    17.6.1 Doxygen translator design

    + + +

    +If this functionality is turned on, SWIG places all comments found +into the SWIG parse tree. Nodes contain an additional attribute +called doxygen when a comment is present. Individual nodes +containing Doxygen with Structural Indicators, such as @file, as their +first command, are also present in the parse tree. These individual +"blobs" of Doxygen such as : +

    +
    +/*! This is describing function Foo
    + \param x some random variable
    + \author Bob
    + \return Foo
    + */
    +
    + +

    +are passed on individually to the Doxygen Translator module. This +module builds its own private parse tree and hands it to a separate +class for translation into the target documentation language. For +example, JavaDocConverter is the Javadoc module class. +

    + +

    17.6.2 Debugging the Doxygen parser and translator

    + + +

    +There are two handy command line options, that enable lots of +detailed debug information printing. +

    + +
    +  -debug-doxygen-parser     - Display Doxygen parser module debugging information
    +  -debug-doxygen-translator - Display Doxygen translator module debugging information
    +
    + +

    17.6.3 Tests

    + + +

    +Doxygen tests have been added to the regular SWIG test-suite. +There are a number of tests beginning doxygen_ in the Examples/test-suite sub-directory. +

    + +

    +Like any other SWIG test case, the tests are included in Examples/test-suite/common.mk and can be tested with +commands like make check-test-suite or make check-python-test-suite. +To run them individually, type +make -s <testname>.cpptest in the language-specific sub-directory in +Examples/test-suite directory. For example: +

    + +
    +  Examples/test-suite/java $ make -s doxygen_parsing.cpptest
    +
    + +

    +If the test fails, both expected and translated comments are printed to +std out, but also written to files expected.txt +and got.txt. Since it is often difficult to find a single +character difference in several lines of text, we can use some diff +tool, for example: +

    + +
    +  Examples/test-suite/java $ kdiff3 expected.txt got.txt
    +
    + + +

    +Runtime tests in Java are implemented using Javadoc doclets. To make that work, you +should have tools.jar from the JDK in your classpath. Or you should have JAVA_HOME +environment variable defined and pointing to the JDK location. +

    +

    +The Java's comment parsing code (the testing part) is located in commentParser.java. +It checks the generated code. It is possible +to run this file as a stand-alone program, with java commentParser <some java package>, +and it will print the list of comments found in the specified directory (in the format it has used +in the runtime tests). So, when you want to create a new Doxygen test case, +just copy an existing one and replace the actual comment content (section of entries in +form 'wantedComments.put(...)' with the output of the above command. +

    +

    +Runtime tests in Python are just plain string comparisons of the __doc__ +properties. +

    + +

    17.7 Extending to other languages

    + + +

    +In general, an extension to another language requires a fairly deep understanding of the target language module, such as Modules/python.cxx for Python. +Searching for "doxygen" in the java.cxx module can give you a good idea of the process for placing documentation comments into the correct areas. +The basic gist is that anywhere a comment may reside on a node, there needs to be a catch for it in front of where that function, class, or other object is written out to a target language file. +The other half of extension is building a target documentation language comment generator that handles one blob at a time. +However, this is relatively simple and nowhere near as complex as the wrapper generating modules in SWIG. +See Source/Doxygen/javadoc.cxx for a good example. +The target language module passes the Doxygen Translator the blob to translate, and receives back the translated text. +

    +

    + What is given to the Doxygen Translator +

    +
    +/*! This is describing function Foo
    + \param x some random variable
    + \author Bob
    + \return Foo
    + */
    +
    +

    + What is received back by java.cxx +

    +
    +/** This is describing function Foo
    + *
    + * @param x some random variable
    + * @author Bob
    + * @return Foo
    + */
    +
    +

    Development of the comment translator itself is simplified by the fact that the Doxygen Translator module can easily include a main function and thus be developed, compiled, and tested independently of SWIG. +

    + + + diff --git a/Doc/Manual/Extending.html b/Doc/Manual/Extending.html index e44d53084..5a640fbdc 100644 --- a/Doc/Manual/Extending.html +++ b/Doc/Manual/Extending.html @@ -7,7 +7,7 @@ -

    41 Extending SWIG to support new languages

    +

    39 Extending SWIG to support new languages

  • Documentation -
  • Prerequisites for adding a new language module to the SWIG distribution
  • Coding style guidelines +
  • Target language status + +
  • Prerequisites for adding a new language module to the SWIG distribution
  • Debugging Options
  • Guide to parse tree nodes @@ -76,7 +81,7 @@ -

    41.1 Introduction

    +

    39.1 Introduction

    @@ -92,7 +97,7 @@ Also, this chapter is not meant to be a hand-holding tutorial. As a starting po you should probably look at one of SWIG's existing modules.

    -

    41.2 Prerequisites

    +

    39.2 Prerequisites

    @@ -122,7 +127,7 @@ obvious, but almost all SWIG directives as well as the low-level generation of wrapper code are driven by C++ datatypes.

    -

    41.3 The Big Picture

    +

    39.3 The Big Picture

    @@ -159,7 +164,7 @@ role in making the system work. For example, both typemaps and declaration anno based on pattern matching and interact heavily with the underlying type system.

    -

    41.4 Execution Model

    +

    39.4 Execution Model

    @@ -204,7 +209,7 @@ latter stage of compilation. The next few sections briefly describe some of these stages.

    -

    41.4.1 Preprocessing

    +

    39.4.1 Preprocessing

    @@ -243,7 +248,7 @@ of swig.swg looks like this: /* Access control directives */ -#define %immutable %feature("immutable","1") +#define %immutable %feature("immutable", "1") #define %mutable %feature("immutable") /* Directives for callback functions */ @@ -278,14 +283,14 @@ or perl5.swg.

    -As a debugging aide, the text that SWIG feeds to its C++ parser can be +As a debugging aid, the text that SWIG feeds to its C++ parser can be obtained by running swig -E interface.i. This output probably isn't too useful in general, but it will show how macros have been expanded as well as everything else that goes into the low-level construction of the wrapper code.

    -

    41.4.2 Parsing

    +

    39.4.2 Parsing

    @@ -306,7 +311,7 @@ datatype such as int or void. type may be qualified with a qualifier such as const or volatile. declarator is a name with additional type-construction modifiers attached to it (pointers, arrays, references, functions, etc.). Examples of declarators include *x, **x, x[20], and -(*x)(int,double). The initializer may be a value assigned using = or +(*x)(int, double). The initializer may be a value assigned using = or body of code enclosed in braces { ... }.

    @@ -372,7 +377,7 @@ For example, in an old C program, you might see things like this:
    -foo(a,b) {
    +foo(a, b) {
     ...
     }
     
    @@ -386,7 +391,7 @@ returning a foo and taking types a and b as arguments).

    -

    41.4.3 Parse Trees

    +

    39.4.3 Parse Trees

    @@ -516,8 +521,8 @@ $ swig -c++ -python -debug-module 4 example.i +++ cdecl ---------------------------------------- | sym:name - "move" | name - "move" - | decl - "f(double,double)." - | parms - double ,double + | decl - "f(double, double)." + | parms - double, double | type - "void" | sym:symtab - 0x40194140 | @@ -641,7 +646,7 @@ $ swig -c++ -python -debug-module 4 example.i

  • -

    41.4.4 Attribute namespaces

    +

    39.4.4 Attribute namespaces

    @@ -660,7 +665,7 @@ that matches the name of the target language. For example, python:foo perl:foo.

    -

    41.4.5 Symbol Tables

    +

    39.4.5 Symbol Tables

    @@ -729,7 +734,7 @@ For instance, the following example uses %rename in reverse to generate

     %rename(foo) foo_i(int);
    -%rename(foo) foo_d(double;
    +%rename(foo) foo_d(double);
     
     void foo_i(int);
     void foo_d(double);
    @@ -751,7 +756,7 @@ example.i:5. Previous declaration is foo_i(int )
     
    -

    41.4.6 The %feature directive

    +

    39.4.6 The %feature directive

    @@ -772,8 +777,8 @@ low-level %feature directive. For example: ... class Foo { public: - Object *getitem(int index) throws(badindex); - ... + Object *getitem(int index) throws(badindex); + ... }; @@ -807,7 +812,7 @@ For example, the exception code above is simply stored without any modifications.

    -

    41.4.7 Code Generation

    +

    39.4.7 Code Generation

    @@ -826,7 +831,7 @@ transformed. For example, suppose you are wrapping a class like this:

     class Foo {
     public:
    -    virtual int *bar(int x);
    +  virtual int *bar(int x);
     };
     
    @@ -929,7 +934,7 @@ public : The role of these functions is described shortly.

    -

    41.4.8 SWIG and XML

    +

    39.4.8 SWIG and XML

    @@ -942,7 +947,7 @@ internal data structures, it may be useful to keep XML in the back of your mind as a model.

    -

    41.5 Primitive Data Structures

    +

    39.5 Primitive Data Structures

    @@ -988,7 +993,7 @@ typedef Hash Typetab; -

    41.5.1 Strings

    +

    39.5.1 Strings

    @@ -1129,7 +1134,7 @@ Returns the number of replacements made (if any). -

    41.5.2 Hashes

    +

    39.5.2 Hashes

    @@ -1206,7 +1211,7 @@ Returns the list of hash table keys. -

    41.5.3 Lists

    +

    39.5.3 Lists

    @@ -1295,7 +1300,7 @@ If t is not a standard object, it is assumed to be a char * and is used to create a String object. -

    41.5.4 Common operations

    +

    39.5.4 Common operations

    The following operations are applicable to all datatypes. @@ -1350,7 +1355,7 @@ objects and report errors. Gets the line number associated with x. -

    41.5.5 Iterating over Lists and Hashes

    +

    39.5.5 Iterating over Lists and Hashes

    To iterate over the elements of a list or a hash table, the following functions are used: @@ -1381,21 +1386,21 @@ List *l = (some list); Iterator i; for (i = First(l); i.item; i = Next(i)) { - Printf(stdout,"%s\n", i.item); + Printf(stdout, "%s\n", i.item); } Hash *h = (some hash); Iterator j; for (j = First(j); j.item; j= Next(j)) { - Printf(stdout,"%s : %s\n", j.key, j.item); + Printf(stdout, "%s : %s\n", j.key, j.item); } -

    41.5.6 I/O

    +

    39.5.6 I/O

    Special I/O functions are used for all internal I/O. These operations @@ -1414,7 +1419,7 @@ operators have the same meaning.

    -int Printv(String_or_FILE *f, String_or_char *arg1,..., NULL) +int Printv(String_or_FILE *f, String_or_char *arg1, ..., NULL)

    @@ -1469,7 +1474,7 @@ Same as the C ungetc() function.
    Same as the C seek() function. offset is the number -of bytes. whence is one of SEEK_SET,SEEK_CUR, +of bytes. whence is one of SEEK_SET, SEEK_CUR, or SEEK_END..
    @@ -1515,9 +1520,9 @@ common to see small code fragments of code generated using code like this:
     /* Print into a string */
     String *s = NewString("");
    -Printf(s,"Hello\n");
    +Printf(s, "Hello\n");
     for (i = 0; i < 10; i++) {
    -    Printf(s,"%d\n", i);
    +  Printf(s, "%d\n", i);
     }
     ...
     /* Print string into a file */
    @@ -1529,7 +1534,7 @@ Printf(f, "%s\n", s);
     Similarly, the preprocessor and parser all operate on string-files.
     

    -

    41.6 Navigating and manipulating parse trees

    +

    39.6 Navigating and manipulating parse trees

    Parse trees are built as collections of hash tables. Each node is a hash table in which @@ -1576,7 +1581,7 @@ return the node for the first class member.
    Returns the last child node. You might use this if you wanted to append a new -node to the of a class. +node to the children of a class.

    @@ -1663,7 +1668,7 @@ Deletes a node from the parse tree. Deletion reconnects siblings and properly u the parent so that sibling nodes are unaffected.

    -

    41.7 Working with attributes

    +

    39.7 Working with attributes

    @@ -1674,10 +1679,10 @@ Since parse tree nodes are just hash tables, attributes are accessed using the <

     int functionHandler(Node *n) {
    -    String *name    = Getattr(n,"name");
    -    String *symname = Getattr(n,"sym:name");
    -    SwigType *type  = Getattr(n,"type");
    -    ...
    +  String *name    = Getattr(n, "name");
    +  String *symname = Getattr(n, "sym:name");
    +  SwigType *type  = Getattr(n, "type");
    +  ...
     }
     
    @@ -1691,7 +1696,7 @@ For example:
     ...
    -Setattr(n,"python:docstring", doc);     /* Store docstring */
    +Setattr(n, "python:docstring", doc);     /* Store docstring */
     ...
     
    @@ -1702,9 +1707,9 @@ A quick way to check the value of an attribute is to use the checkAttribute(
    -if (checkAttribute(n,"storage","virtual")) {
    -   /* n is virtual */
    -   ...
    +if (checkAttribute(n, "storage", "virtual")) {
    +  /* n is virtual */
    +  ...
     }
     
    @@ -1723,7 +1728,7 @@ the following functions are used:
    Saves a copy of attributes name1, name2, etc. from node n. Copies of the attributes are actually resaved in the node in a different namespace which is -set by the ns argument. For example, if you call Swig_save("foo",n,"type",NIL), +set by the ns argument. For example, if you call Swig_save("foo", n, "type", NIL), then the "type" attribute will be copied and saved as "foo:type". The namespace name itself is stored in the "view" attribute of the node. If necessary, this can be examined to find out where previous values of attributes might have been saved. @@ -1750,17 +1755,17 @@ Calls can be nested if necessary. Here is an example that shows how the functio
     int variableHandler(Node *n) {
    -    Swig_save("variableHandler",n,"type","sym:name",NIL);
    -    String *symname = Getattr(n,"sym:name");
    -    SwigType *type  = Getattr(n,"type");
    -    ...
    -    Append(symname,"_global");         // Change symbol name
    -    SwigType_add_pointer(type);        // Add pointer
    -    ...
    -    generate wrappers
    -    ...
    -    Swig_restore(n);                  // Restore original values
    -    return SWIG_OK;
    +  Swig_save("variableHandler", n, "type", "sym:name", NIL);
    +  String *symname = Getattr(n, "sym:name");
    +  SwigType *type  = Getattr(n, "type");
    +  ...
    +  Append(symname, "_global");        // Change symbol name
    +  SwigType_add_pointer(type);        // Add pointer
    +  ...
    +  generate wrappers
    +  ...
    +  Swig_restore(n);                  // Restore original values
    +  return SWIG_OK;
     }
     
    @@ -1780,7 +1785,7 @@ the attribute is optional. Swig_restore() must always be called after function.
    -

    41.8 Type system

    +

    39.8 Type system

    @@ -1789,7 +1794,7 @@ pointers, references, and pointers to members. A detailed discussion of type theory is impossible here. However, let's cover the highlights.

    -

    41.8.1 String encoding of types

    +

    39.8.1 String encoding of types

    @@ -1808,7 +1813,7 @@ C datatype SWIG encoding (strings) int "int" int * "p.int" const int * "p.q(const).int" -int (*x)(int,double) "p.f(int,double).int" +int (*x)(int, double) "p.f(int, double).int" int [20][30] "a(20).a(30).int" int (F::*)(int) "m(F).f(int).int" vector<int> * "p.vector<(int)>" @@ -1817,8 +1822,8 @@ vector<int> * "p.vector<(int)>"

    Reading the SWIG encoding is often easier than figuring out the C code---just -read it from left to right. For a type of "p.f(int,double).int" is -a "pointer to a function(int,double) that returns int". +read it from left to right. For a type of "p.f(int, double).int" is +a "pointer to a function(int, double) that returns int".

    @@ -1854,7 +1859,7 @@ an extremely perverted example:

    -`p.a(10).p.f(int,p.f(int).int)` foo(int, int (*x)(int));
    +`p.a(10).p.f(int, p.f(int).int)` foo(int, int (*x)(int));
     
    @@ -1864,7 +1869,7 @@ This corresponds to the immediately obvious C declaration:
    -(*(*foo(int,int (*)(int)))[10])(int,int (*)(int));
    +(*(*foo(int, int (*)(int)))[10])(int, int (*)(int));
     
    @@ -1890,7 +1895,7 @@ make the final type, the two parts are just joined together using string concatenation.

    -

    41.8.2 Type construction

    +

    39.8.2 Type construction

    @@ -1947,7 +1952,7 @@ Returns number of array dimensions of ty.

    -String* SwigType_array_getdim(SwigType *ty,int n) +String* SwigType_array_getdim(SwigType *ty, int n)

    @@ -2059,7 +2064,7 @@ Returns the prefix of a type. For example, if ty is ty is unmodified.
    -

    41.8.3 Type tests

    +

    39.8.3 Type tests

    @@ -2146,7 +2151,7 @@ Checks if ty is a varargs type. Checks if ty is a templatized type. -

    41.8.4 Typedef and inheritance

    +

    39.8.4 Typedef and inheritance

    @@ -2248,7 +2253,7 @@ Fully reduces ty according to typedef rules. Resulting datatype will consist only of primitive typenames. -

    41.8.5 Lvalues

    +

    39.8.5 Lvalues

    @@ -2285,7 +2290,7 @@ Literal y; // type = 'Literal', ltype='p.char' -

    41.8.6 Output functions

    +

    39.8.6 Output functions

    @@ -2347,7 +2352,7 @@ SWIG, but is most commonly associated with type-descriptor objects that appear in wrappers (e.g., SWIGTYPE_p_double). -

    41.9 Parameters

    +

    39.9 Parameters

    @@ -2375,10 +2380,10 @@ code like this: Parm *parms; Parm *p; for (p = parms; p; p = nextSibling(p)) { - SwigType *type = Getattr(p,"type"); - String *name = Getattr(p,"name"); - String *value = Getattr(p,"value"); - ... + SwigType *type = Getattr(p, "type"); + String *name = Getattr(p, "name"); + String *value = Getattr(p, "value"); + ... } @@ -2446,7 +2451,7 @@ included. Used to emit prototypes. Returns the number of required (non-optional) arguments in p. -

    41.10 Writing a Language Module

    +

    39.10 Writing a Language Module

    @@ -2461,7 +2466,7 @@ describes the creation of a minimal Python module. You should be able to extra this to other languages.

    -

    41.10.1 Execution model

    +

    39.10.1 Execution model

    @@ -2471,7 +2476,7 @@ the parsing of command line options, all aspects of code generation are controll different methods of the Language that must be defined by your module.

    -

    41.10.2 Starting out

    +

    39.10.2 Starting out

    @@ -2537,7 +2542,7 @@ also return a pointer to the base class (Language) so that only the int Save the code for your language module in a file named "python.cxx" and place this file in the Source/Modules directory of the SWIG distribution. To ensure that your module is compiled into SWIG along with the other language modules, -modify the file Source/Modules/Makefile.am to include the additional source +modify the file Source/Makefile.am to include the additional source files. In addition, modify the file Source/Modules/swigmain.cxx with an additional command line option that activates the module. Read the source---it's straightforward.

    @@ -2579,7 +2584,7 @@ that activates your module. For example, swig -python foo.i. The messages from your new module should appear.

    -

    41.10.3 Command line options

    +

    39.10.3 Command line options

    @@ -2592,36 +2597,36 @@ command line options, simply use code similar to this:

     void Language::main(int argc, char *argv[]) {
       for (int i = 1; i < argc; i++) {
    -      if (argv[i]) {
    -          if(strcmp(argv[i],"-interface") == 0) {
    -            if (argv[i+1]) {
    -              interface = NewString(argv[i+1]);
    -              Swig_mark_arg(i);
    -              Swig_mark_arg(i+1);
    -              i++;
    -            } else {
    -              Swig_arg_error();
    -            }
    -          } else if (strcmp(argv[i],"-globals") == 0) {
    -            if (argv[i+1]) {
    -              global_name = NewString(argv[i+1]);
    -              Swig_mark_arg(i);
    -              Swig_mark_arg(i+1);
    -              i++;
    -            } else {
    -              Swig_arg_error();
    -            }
    -          } else if ( (strcmp(argv[i],"-proxy") == 0)) {
    -            proxy_flag = 1;
    -            Swig_mark_arg(i);
    -          } else if (strcmp(argv[i],"-keyword") == 0) {
    -            use_kw = 1;
    -            Swig_mark_arg(i);
    -          } else if (strcmp(argv[i],"-help") == 0) {
    -            fputs(usage,stderr);
    -          }
    -          ...
    +    if (argv[i]) {
    +      if (strcmp(argv[i], "-interface") == 0) {
    +        if (argv[i+1]) {
    +          interface = NewString(argv[i+1]);
    +          Swig_mark_arg(i);
    +          Swig_mark_arg(i+1);
    +          i++;
    +        } else {
    +          Swig_arg_error();
    +        }
    +      } else if (strcmp(argv[i], "-globals") == 0) {
    +        if (argv[i+1]) {
    +          global_name = NewString(argv[i+1]);
    +          Swig_mark_arg(i);
    +          Swig_mark_arg(i+1);
    +          i++;
    +        } else {
    +          Swig_arg_error();
    +        }
    +      } else if ((strcmp(argv[i], "-proxy") == 0)) {
    +        proxy_flag = 1;
    +        Swig_mark_arg(i);
    +      } else if (strcmp(argv[i], "-keyword") == 0) {
    +        use_kw = 1;
    +        Swig_mark_arg(i);
    +      } else if (strcmp(argv[i], "-help") == 0) {
    +        fputs(usage, stderr);
           }
    +      ...
    +    }
       }
     }
     
    @@ -2638,7 +2643,7 @@ to mark the option as valid. If you forget to do this, SWIG will terminate wit unrecognized command line option error.

    -

    41.10.4 Configuration and preprocessing

    +

    39.10.4 Configuration and preprocessing

    @@ -2650,19 +2655,19 @@ insert some code like this:

     void main(int argc, char *argv[]) {
    -   ... command line options ...
    +  ... command line options ...
     
    -   /* Set language-specific subdirectory in SWIG library */
    -   SWIG_library_directory("python");
    +  /* Set language-specific subdirectory in SWIG library */
    +  SWIG_library_directory("python");
     
    -   /* Set language-specific preprocessing symbol */
    -   Preprocessor_define("SWIGPYTHON 1", 0);
    +  /* Set language-specific preprocessing symbol */
    +  Preprocessor_define("SWIGPYTHON 1", 0);
     
    -   /* Set language-specific configuration file */
    -   SWIG_config_file("python.swg");
    +  /* Set language-specific configuration file */
    +  SWIG_config_file("python.swg");
     
    -   /* Set typemap language (historical) */
    -   SWIG_typemap_lang("python");
    +  /* Set typemap language (historical) */
    +  SWIG_typemap_lang("python");
     }
     
    @@ -2687,7 +2692,7 @@ an implementation file python.cxx and a configuration file python.swg.

    -

    41.10.5 Entry point to code generation

    +

    39.10.5 Entry point to code generation

    @@ -2721,31 +2726,31 @@ An outline of top() might be as follows:

     int Python::top(Node *n) {
     
    -   /* Get the module name */
    -   String *module = Getattr(n,"name");
    +  /* Get the module name */
    +  String *module = Getattr(n, "name");
     
    -   /* Get the output file name */
    -   String *outfile = Getattr(n,"outfile");
    +  /* Get the output file name */
    +  String *outfile = Getattr(n, "outfile");
     
    -   /* Initialize I/O (see next section) */
    -   ...
    +  /* Initialize I/O (see next section) */
    +  ...
     
    -   /* Output module initialization code */
    -   ...
    +  /* Output module initialization code */
    +  ...
     
    -   /* Emit code for children */
    -   Language::top(n);
    +  /* Emit code for children */
    +  Language::top(n);
     
    -   ...
    -   /* Cleanup files */
    -   ...
    +  ...
    +  /* Cleanup files */
    +  ...
     
    -   return SWIG_OK;
    +  return SWIG_OK;
     }
     
    -

    41.10.6 Module I/O and wrapper skeleton

    +

    39.10.6 Module I/O and wrapper skeleton

    @@ -2777,62 +2782,62 @@ such as:
     class PYTHON : public Language {
     protected:
    -   /* General DOH objects used for holding the strings */
    -   File *f_begin;
    -   File *f_runtime;
    -   File *f_header;
    -   File *f_wrappers;
    -   File *f_init;
    +  /* General DOH objects used for holding the strings */
    +  File *f_begin;
    +  File *f_runtime;
    +  File *f_header;
    +  File *f_wrappers;
    +  File *f_init;
     
     public:
    -   ...
    +  ...
     
     };
     
     int Python::top(Node *n) {
     
    -   ...
    +  ...
     
    -   /* Initialize I/O */
    -   f_begin = NewFile(outfile, "w", SWIG_output_files());
    -   if (!f_begin) {
    -      FileErrorDisplay(outfile);
    -      SWIG_exit(EXIT_FAILURE);
    -   }
    -   f_runtime = NewString("");
    -   f_init = NewString("");
    -   f_header = NewString("");
    -   f_wrappers = NewString("");
    +  /* Initialize I/O */
    +  f_begin = NewFile(outfile, "w", SWIG_output_files());
    +  if (!f_begin) {
    +    FileErrorDisplay(outfile);
    +    SWIG_exit(EXIT_FAILURE);
    +  }
    +  f_runtime = NewString("");
    +  f_init = NewString("");
    +  f_header = NewString("");
    +  f_wrappers = NewString("");
     
    -   /* Register file targets with the SWIG file handler */
    -   Swig_register_filebyname("begin", f_begin);
    -   Swig_register_filebyname("header", f_header);
    -   Swig_register_filebyname("wrapper", f_wrappers);
    -   Swig_register_filebyname("runtime", f_runtime);
    -   Swig_register_filebyname("init", f_init);
    +  /* Register file targets with the SWIG file handler */
    +  Swig_register_filebyname("begin", f_begin);
    +  Swig_register_filebyname("header", f_header);
    +  Swig_register_filebyname("wrapper", f_wrappers);
    +  Swig_register_filebyname("runtime", f_runtime);
    +  Swig_register_filebyname("init", f_init);
     
    -   /* Output module initialization code */
    -   Swig_banner(f_begin);
    -   ...
    +  /* Output module initialization code */
    +  Swig_banner(f_begin);
    +  ...
     
    -   /* Emit code for children */
    -   Language::top(n);
    +  /* Emit code for children */
    +  Language::top(n);
     
    -   ...
    -   /* Write all to the file */
    -   Dump(f_runtime, f_begin);
    -   Dump(f_header, f_begin);
    -   Dump(f_wrappers, f_begin);
    -   Wrapper_pretty_print(f_init, f_begin);
    +  ...
    +  /* Write all to the file */
    +  Dump(f_runtime, f_begin);
    +  Dump(f_header, f_begin);
    +  Dump(f_wrappers, f_begin);
    +  Wrapper_pretty_print(f_init, f_begin);
     
    -   /* Cleanup files */
    -   Delete(f_runtime);
    -   Delete(f_header);
    -   Delete(f_wrappers);
    -   Delete(f_init);
    -   Delete(f_begin);
    +  /* Cleanup files */
    +  Delete(f_runtime);
    +  Delete(f_header);
    +  Delete(f_wrappers);
    +  Delete(f_init);
    +  Delete(f_begin);
     
    -   return SWIG_OK;
    +  return SWIG_OK;
     }
     
    @@ -2858,15 +2863,15 @@ A simple modification to write some basic details to the wrapper looks like this
     int Python::functionWrapper(Node *n) {
       /* Get some useful attributes of this function */
    -  String   *name   = Getattr(n,"sym:name");
    -  SwigType *type   = Getattr(n,"type");
    -  ParmList *parms  = Getattr(n,"parms");
    +  String   *name   = Getattr(n, "sym:name");
    +  SwigType *type   = Getattr(n, "type");
    +  ParmList *parms  = Getattr(n, "parms");
       String   *parmstr= ParmList_str_defaultargs(parms); // to string
       String   *func   = SwigType_str(type, NewStringf("%s(%s)", name, parmstr));
    -  String   *action = Getattr(n,"wrap:action");
    +  String   *action = Getattr(n, "wrap:action");
     
    -  Printf(f_wrappers,"functionWrapper   : %s\n", func);
    -  Printf(f_wrappers,"           action : %s\n", action);
    +  Printf(f_wrappers, "functionWrapper   : %s\n", func);
    +  Printf(f_wrappers, "           action : %s\n", action);
       return SWIG_OK;
     }
     
    @@ -2881,19 +2886,19 @@ This will now produce some useful information within your wrapper file. functionWrapper : void delete_Shape(Shape *self) action : delete arg1; -functionWrapper : void Shape_x_set(Shape *self,double x) +functionWrapper : void Shape_x_set(Shape *self, double x) action : if (arg1) (arg1)->x = arg2; functionWrapper : double Shape_x_get(Shape *self) action : result = (double) ((arg1)->x); -functionWrapper : void Shape_y_set(Shape *self,double y) +functionWrapper : void Shape_y_set(Shape *self, double y) action : if (arg1) (arg1)->y = arg2; ... -

    41.10.7 Low-level code generators

    +

    39.10.7 Low-level code generators

    @@ -2918,7 +2923,7 @@ In general most language wrappers look a little like this:

    -/* wrapper for TYPE3 some_function(TYPE1,TYPE2); */
    +/* wrapper for TYPE3 some_function(TYPE1, TYPE2); */
     RETURN_TYPE _wrap_some_function(ARGS){
       TYPE1 arg1;
       TYPE2 arg2;
    @@ -2929,7 +2934,7 @@ RETURN_TYPE _wrap_some_function(ARGS){
       if(ARG2 is not of TYPE2) goto fail;
       arg2=(convert ARG2);
     
    -  result=some_function(arg1,arg2);
    +  result=some_function(arg1, arg2);
     
       convert 'result' to whatever the language wants;
     
    @@ -2973,9 +2978,9 @@ There are a lot of issues to address.
     
     virtual int functionWrapper(Node *n) {
       /* get useful attributes */
    -  String   *name   = Getattr(n,"sym:name");
    -  SwigType *type   = Getattr(n,"type");
    -  ParmList *parms  = Getattr(n,"parms");
    +  String   *name   = Getattr(n, "sym:name");
    +  SwigType *type   = Getattr(n, "type");
    +  ParmList *parms  = Getattr(n, "parms");
       ...
     
       /* create the wrapper object */
    @@ -2988,7 +2993,7 @@ virtual int functionWrapper(Node *n) {
       ....
     
       /* write the wrapper function definition */
    -  Printv(wrapper->def,"RETURN_TYPE ", wname, "(ARGS) {",NIL);
    +  Printv(wrapper->def, "RETURN_TYPE ", wname, "(ARGS) {", NIL);
     
       /* if any additional local variable needed, add them now */
       ...
    @@ -3006,7 +3011,7 @@ virtual int functionWrapper(Node *n) {
       ....
     
       /* Emit the function call */
    -  emit_action(n,wrapper);
    +  emit_action(n, wrapper);
     
       /* return value if necessary  */
       ....
    @@ -3026,11 +3031,11 @@ virtual int functionWrapper(Node *n) {
       /* Close the function(error) */
       Printv(wrapper->code, "return ERROR;\n", "}\n", NIL);
     
    -  /* final substititions if applicable */
    +  /* final substitutions if applicable */
       ...
     
       /* Dump the function out */
    -  Wrapper_print(wrapper,f_wrappers);
    +  Wrapper_print(wrapper, f_wrappers);
     
       /* tidy up */
       Delete(wname);
    @@ -3047,7 +3052,7 @@ but without the typemaps, there is still work to do.
     

    -

    41.10.8 Configuration files

    +

    39.10.8 Configuration files

    @@ -3164,7 +3169,7 @@ these kinds of problems.

    Examples/Makefile.in -
    Nothing special here; see comments at top the of this file +
    Nothing special here; see comments at the top of this file and look to the existing languages for examples.
    Examples/qux99/check.list @@ -3191,7 +3196,7 @@ politely displays the ignoring language message. -

    41.10.9 Runtime support

    +

    39.10.9 Runtime support

    @@ -3200,7 +3205,7 @@ Discuss the kinds of functions typically needed for SWIG runtime support (e.g. the SWIG files that implement those functions.

    -

    41.10.10 Standard library files

    +

    39.10.10 Standard library files

    @@ -3219,7 +3224,7 @@ The following are the minimum that are usually supported: Please copy these and modify for any new language.

    -

    41.10.11 User examples

    +

    39.10.11 User examples

    @@ -3248,7 +3253,7 @@ during this process, see the section on .

    -

    41.10.12 Test driven development and the test-suite

    +

    39.10.12 Test driven development and the test-suite

    @@ -3307,7 +3312,7 @@ It is therefore essential that the runtime tests are written in a manner that di but error/exception out with an error message on stderr on failure.

    -

    41.10.12.1 Running the test-suite

    +

    39.10.12.1 Running the test-suite

    @@ -3499,7 +3504,7 @@ It can be run in the same way as the other language test-suites, replacing [lang The test cases used and the way it works is described in Examples/test-suite/errors/Makefile.in.

    -

    41.10.13 Documentation

    +

    39.10.13 Documentation

    @@ -3531,64 +3536,7 @@ Some topics that you'll want to be sure to address include: if available. -

    41.10.14 Prerequisites for adding a new language module to the SWIG distribution

    - - -

    -If you wish for a new language module to be distributed with SWIG, -which we encourage for all popular languages, there are a few requirements. -While we appreciate that getting all aspects of a new language working -won't happen at the outset, there are a set of minimum requirements before -a module can be committed into the official Github repository for distribution with future -versions of SWIG. The following are really a summary of this whole section with -details being outlined earlier on. -

    - -
      -
    1. - Demonstrate basic C code working by porting the "simple" example including - a runtime test, see for example Examples/python/simple. -
    2. -
    3. - Demonstrate basic C++ code working by porting the "class" example including - a runtime test, see for example Examples/python/class. -
    4. -
    5. - Modify configure.ac, Makefile.in and Examples/Makefile.in to run - these examples. Please make sure that if the new language is not - installed properly on a box, make -k check should still work by - skipping the tests and examples for the new language module. -
    6. -
    7. - Get the test-suite running for the new language (make check-[lang]-test-suite). - While the test-suite tests many corner cases, - we'd expect the majority of it to work by compiling the generated code - correctly as most of the corner cases are covered in the SWIG core. Get - at least one C and one C++ runtime test running in the test-suite. -
    8. -
    9. - Provide a chapter in the html documentation on the basics of using - the language module. -
    10. -
    11. - Ensure your source code is formatted according to the coding style guidelines. -
    12. -
    13. - Finally, email the SWIG developers with a patch and a demonstration of - commitment to maintaining the language module, - certainly in the short term and ideally long term. -
    14. -
    - -

    -Once accepted into the official Git repository, development efforts should concentrate on -getting the entire test-suite to work with plenty of runtime tests. -Runtime tests should be for existing testcases and new test cases -should be added should there be an area not already covered by -the existing tests. -

    - -

    41.10.15 Coding style guidelines

    +

    39.10.14 Coding style guidelines

    @@ -3612,7 +3560,193 @@ The generated C/C++ code should also follow this style as close as possible. How should be avoided as unlike the SWIG developers, users will never have consistent tab settings.

    -

    41.11 Debugging Options

    + +

    39.10.15 Target language status

    + + +

    +Target languages are given a status of either 'Supported' or 'Experimental' depending on their maturity as broadly outlined in +the Target language introduction. +This section provides more details on how this status is given. +

    + +

    39.10.15.1 Supported status

    + + +

    +A target language is given the 'Supported' status when +

    + +
      +
    • + It is in a mature, well functioning state. +
    • +
    • + It has its own comprehensive chapter in the documentation. + The level of documentation should be comprehensive and match the standard of the other mature modules. + Python and Java are good references.
    • +
    • + It passes all of the main SWIG test-suite. + The main test-suite is defined by the tests in the C_TEST_CASES, CPP_TEST_CASES and MULTI_CPP_TEST_CASES lists in Examples/test-suite/common.mk. + The tests in CPP11_TEST_CASES will also be required in the near future. +
    • +
    • + The test-suite must also include at least twenty wide-ranging runtime tests. + The most mature languages have a few hundred runtime tests. + Note that porting runtime tests from another language module is a quick and easy way to achieve this. +
    • +
    • + It supports the vast majority of SWIG features. + Some more advanced features, such as, directors, full nested class support and target language namespaces (nspace) may be unimplemented. + A few support libraries may be missing, for example, a small number of STL libraries.
    • +
    • + It provides strong backwards compatibility between releases. + Each point release must aim to be fully backwards compatible. + A point release version is the 3rd version digit, so each of the x.y.* versions should be backwards compatible. + Backwards compatibility breakages can occur in a new major or minor version if absolutely necessary and if documented. + A major or minor version is the first or second digit in the three digit version. +
    • +
    • + Fixing unintended regressions in the Supported languages will be given higher priority over experimental languages by the core SWIG developers. +
    • +
    • + Examples must be available and run successfully. +
    • +
    • + The examples and test-suite must be fully functioning on the Travis Continuous Integration platform. +
    • +
    + +

    39.10.15.2 Experimental status

    + + +

    +A target language is given the 'Experimental' status when +

    + +
      +
    • + It is of sub-standard quality, failing to meet the above 'Supported' status. +
    • +
    • + It is somewhere between the mid to mature stage of development. +
    • +
    • + It is in need of help to finish development. +
    • +
    + +

    +Some minimum requirements and notes about languages with the 'Experimental' status: +

    + +
      +
    • + Will at least implement basic functionality - support wrapping C functions and simple C++ classes and templates. +
    • +
    • + Have its own documentation chapter containing a reasonable level of detail. + The documentation must provide enough basic functionality for a user to get started. +
    • +
    • + Have fully functional examples of basic functionality (the simple and class examples). +
    • +
    • + The test-suite must be implemented and include a few runtime tests for both C and C++ test cases. +
    • +
    • + Failing tests must be put into one of the FAILING_CPP_TESTS or FAILING_C_TESTS lists in the test-suite. + This will ensure the test-suite can be superficially made to pass by ignoring failing tests. + The number of tests in these lists should be no greater than half of the number of tests in the full test-suite. +
    • +
    • + The examples and test-suite must also be fully functioning on the Travis Continuous Integration platform. + However, experimental languages will be set as 'allow_failures'. + This means that pull requests and normal development commits will not break the entire Travis build should an experimental language fail. +
    • +
    • + Any new failed tests will be fixed on a 'best effort' basis by core developers with no promises made. +
    • +
    • + If a language module has an official maintainer, then the maintainer will be requested to focus on fixing test-suite regressions and commit to migrating the module to become a 'Supported' module. +
    • +
    • + If a module does not have an official maintainer, then, as maintenance will be on a 'best efforts' basis by the core maintainers, no guarantees will be provided from one release to the next and regressions may creep in. +
    • +
    • + Experimental target languages will have a (suppressible) warning explaining the Experimental sub-standard status and encourage users to help improve it. +
    • +
    • + No backwards compatibility is guaranteed as the module is effectively 'in development'. + If a language module has an official maintainer, then a backwards compatibility guarantee may be provided at the maintainer's discretion and should be documented as such. +
    • +
    + +

    39.10.16 Prerequisites for adding a new language module to the SWIG distribution

    + + +

    +New target language modules can be included in SWIG and contributions are encouraged for popular languages. +In order to be considered for inclusion, a language must at a minimum fit the 'Experimental' status described above. +

    + +

    +Below are some practical steps that should help meet these requirements. +

    + +
      +
    1. + The "simple" example needs to be working to demonstrate basic C code wrappers. + Port the example from another language, such as from Examples/python/simple. +
    2. +
    3. + The "class" example needs to be working to demonstrate basic C++ code wrappers. + Port the example from another language, such as from Examples/python/class. +
    4. +
    5. + Modify configure.ac, Makefile.in and Examples/Makefile.in to run + these examples. Please make sure that if the new language is not + installed properly on a box, make -k check should still work by + skipping the tests and examples for the new language module. +
    6. +
    7. + Copying an existing language module and adapting the source for it is likely to be the most efficient + approach to fully developing a new module as a number of corner cases are covered in the existing implementations. + The most advanced scripting languages are Python and Ruby. + The most advanced compiled target languages are Java and C#. +
    8. +
    9. + Get the test-suite running for the new language (make check-[lang]-test-suite). + While the test-suite tests many corner cases, + we'd expect the majority of it to work without much effort once the generated code is compiling + correctly for basic functionality as most of the corner cases are covered in the SWIG core. Aim to first get + one C and one C++ runtime test running in the test-suite. + Adding further runtime tests should be a lot easier afterwards by porting existing runtime tests from another language module. +
    10. +
    11. + The structure and contents of the html documentation chapter can be copied and adapted from one of the other language modules. +
    12. +
    13. + Source code can be formatted correctly using the info in the coding style guidelines section. +
    14. +
    15. + When ready, post a patch on Github, join the swig-devel mailing list and email the SWIG developers with a demonstration of + commitment to maintaining the language module, + certainly in the short term and ideally long term. +
    16. +
    + +

    +Once accepted into the official Git repository, development efforts should concentrate on +getting the entire test-suite to work +in order to migrate the language module to the 'Supported' status. +Runtime tests should be added for existing testcases and new test cases +can be added should there be an area not already covered by +the existing tests. +

    + + +

    39.11 Debugging Options

    @@ -3639,7 +3773,7 @@ There are various command line options which can aid debugging a SWIG interface The complete list of command line options for SWIG are available by running swig -help.

    -

    41.12 Guide to parse tree nodes

    +

    39.12 Guide to parse tree nodes

    @@ -4047,7 +4181,7 @@ extern "X" { ... } declaration.

    -

    41.13 Further Development Information

    +

    39.13 Further Development Information

    diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index f25e9850b..c28cc03e1 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -6,7 +6,7 @@ -

    23 SWIG and Go

    +

    24 SWIG and Go

      @@ -57,7 +57,7 @@ the Go programming language see golang.org.

      -

      23.1 Overview

      +

      24.1 Overview

      @@ -86,7 +86,7 @@ type-safe as well. In case of type issues the build will fail and hence SWIG's are not used.

      -

      23.2 Examples

      +

      24.2 Examples

      @@ -101,7 +101,7 @@ SWIG interface file extension for backwards compatibility with Go 1.

      -

      23.3 Running SWIG with Go

      +

      24.3 Running SWIG with Go

      @@ -125,16 +125,15 @@ Go distribution. To generate code for gccgo, you should also use the

      -When using the -cgo option, SWIG will generate files that can be used -directly by go build. Starting with the Go 1.5 distribution the --cgo option has to be given. Put your SWIG interface file in a -directory under GOPATH/src, and give it a name that does not end in the -.swig or .swigcxx extension. Typically the SWIG interface file extension is .i -in this case. +By default SWIG will generate files that can be used directly +by go build. This requires Go 1.2 or later. Put your SWIG +interface file in a directory under GOPATH/src, and give it a name +that does not end in the .swig or .swigcxx extension. +Typically the SWIG interface file extension is .i in this case.

      -% swig -go -cgo example.i
      +% swig -go example.i
       % go install
       
      @@ -144,15 +143,16 @@ usual.

      -To use SWIG without the -cgo option, more steps are required. Recall -that this only works with Go versions before 1.5. When using Go version 1.2 or -later, or when using gccgo, the code generated by SWIG can be linked directly -into the Go program. A typical command sequence when using the Go compiler of -the Go distribution would look like this: +SWIG can be used without cgo, via the -no-cgo option, but +more steps are required. This only works with Go versions before 1.5. +When using Go version 1.2 or later, or when using gccgo, the code +generated by SWIG can be linked directly into the Go program. A +typical command sequence when using the Go compiler of the Go +distribution would look like this:

      -% swig -go example.i
      +% swig -go -no-cgo example.i
       % gcc -c code.c    # The C library being wrapped.
       % gcc -c example_wrap.c
       % go tool 6g example.go
      @@ -169,7 +169,7 @@ sequence for this approach would look like this:
       

      -% swig -go -use-shlib example.i
      +% swig -go -no-cgo -use-shlib example.i
       % gcc -c -fpic example.c
       % gcc -c -fpic example_wrap.c
       % gcc -shared example.o example_wrap.o -o example.so
      @@ -181,7 +181,7 @@ sequence for this approach would look like this:
       
      -

      23.3.1 Go-specific Commandline Options

      +

      24.3.1 Go-specific Commandline Options

      @@ -200,10 +200,15 @@ swig -go -help -cgo -Generate files to be used as input for the Go cgo tool. This - option is required for Go 1.5 and later, and works for Go 1.2 and - later. In the future this option will likely become the - default. +Generate files to be used as input for the Go cgo tool. This is + the default. + + + +-no-cgo +Generate files that can be used directly, rather than via the Go + cgo tool. This option does not work with Go 1.5 or later. It is + required for versions of Go before 1.2. @@ -261,18 +266,25 @@ swig -go -help ignored. + +-import-prefix <prefix> +A prefix to add when turning a %import prefix in the SWIG + interface file into an import statement in the Go file. For + example, with -import-prefix mymodule, a SWIG + interface file %import mypackage will become a Go + import statement import "mymodule/mypackage". -

      23.3.2 Generated Wrapper Files

      +

      24.3.2 Generated Wrapper Files

      There are two different approaches to generating wrapper files, - controlled by SWIG's -cgo option. The -cgo option - works with Go version 1.2 or later. It is required when using Go - version 1.5 or later.

      + controlled by SWIG's -no-cgo option. The -no-cgo + option only works with version of Go before 1.5. It is required + when using versions of Go before 1.2.

      -

      With or without the -cgo option, SWIG will generate the +

      With or without the -no-cgo option, SWIG will generate the following files when generating wrapper code:

        @@ -296,8 +308,8 @@ or C++ compiler.
      -

      When neither the -cgo nor the -gccgo option is - used, SWIG will also generate an additional file:

      +

      When the -no-cgo option is used, and the -gccgo + option is not used, SWIG will also generate an additional file:

      • @@ -308,7 +320,7 @@ combined with the compiled MODULE.go using go tool pack.
      -

      23.4 A tour of basic C/C++ wrapping

      +

      24.4 A tour of basic C/C++ wrapping

      @@ -318,7 +330,7 @@ modifications have to occur. This section briefly covers the essential aspects of this wrapping.

      -

      23.4.1 Go Package Name

      +

      24.4.1 Go Package Name

      @@ -328,7 +340,7 @@ directive. You may override this by using SWIG's -package command line option.

      -

      23.4.2 Go Names

      +

      24.4.2 Go Names

      @@ -360,7 +372,7 @@ followed by that name, and the destructor will be named Delete followed by that name.

      -

      23.4.3 Go Constants

      +

      24.4.3 Go Constants

      @@ -368,7 +380,7 @@ C/C++ constants created via #define or the %constant directive become Go constants, declared with a const declaration. -

      23.4.4 Go Enumerations

      +

      24.4.4 Go Enumerations

      @@ -378,7 +390,7 @@ usual). The values of the enumeration will become variables in Go; code should avoid modifying those variables.

      -

      23.4.5 Go Classes

      +

      24.4.5 Go Classes

      @@ -456,7 +468,7 @@ returns a go interface. If the returned pointer can be null, you can check for this by calling the Swigcptr() method.

      -

      23.4.5.1 Go Class Memory Management

      +

      24.4.5.1 Go Class Memory Management

      @@ -471,7 +483,7 @@ The most Go idiomatic way to manage the memory for some C++ class is to call defer of the DeleteClassName call. Using defer ensures that the memory of the C++ object is freed as soon as the function containing the defer -statement returns. Furthemore defer works great for short-lived +statement returns. Furthermore defer works great for short-lived objects and fits nicely C++'s RAII idiom. Example:

      @@ -512,7 +524,7 @@ func main() {

      Using defer has limitations though, especially when it comes to -long-lived C++ objects whichs lifetimes are hard to predict. For such C++ +long-lived C++ objects whose lifetimes are hard to predict. For such C++ objects a common technique is to store the C++ object into a Go object, and to use the Go function runtime.SetFinalizer to add a finalizer which frees the C++ object when the Go object is freed. It is strongly recommended to read @@ -578,7 +590,7 @@ func (o *GoClassName) Close() {

      -

      23.4.5.2 Go Class Inheritance

      +

      24.4.5.2 Go Class Inheritance

      @@ -590,16 +602,16 @@ Doing the reverse will require an explicit type assertion, which will be checked dynamically.

      -

      23.4.6 Go Templates

      +

      24.4.6 Go Templates

      In order to use C++ templates in Go, you must tell SWIG to create -wrappers for a particular template instantation. To do this, use +wrappers for a particular template instantiation. To do this, use the %template directive. -

      23.4.7 Go Director Classes

      +

      24.4.7 Go Director Classes

      @@ -611,13 +623,13 @@ work is necessary.

      -This subchapter gives a step by step guide how to properly sublass a C++ class +This subchapter gives a step by step guide how to properly subclass a C++ class with a Go type. In general it is strongly recommended to follow this guide completely to avoid common pitfalls with directors in Go.

      -

      23.4.7.1 Example C++ code

      +

      24.4.7.1 Example C++ code

      @@ -639,12 +651,12 @@ public: virtual ~FooBarAbstract() {}; std::string FooBar() { - return this->Foo() + ", " + this->Bar(); + return this->Foo() + ", " + this->Bar(); }; protected: virtual std::string Foo() { - return "Foo"; + return "Foo"; }; virtual std::string Bar() = 0; @@ -689,7 +701,7 @@ be found in the end of the guide.

      -

      23.4.7.2 Enable director feature

      +

      24.4.7.2 Enable director feature

      @@ -724,7 +736,7 @@ documentation on directors.

      -

      23.4.7.3 Constructor and destructor

      +

      24.4.7.3 Constructor and destructor

      @@ -777,7 +789,7 @@ embedding.

      -

      23.4.7.4 Override virtual methods

      +

      24.4.7.4 Override virtual methods

      @@ -785,10 +797,12 @@ In order to override virtual methods on a C++ class with Go methods the NewDirectorClassName constructor functions receives a DirectorInterface argument. The methods in the DirectorInterface are a subset of the public and protected virtual methods -of the C++ class. If the DirectorInterface contains a method with a +of the C++ class. +Virtual methods that have a final specifier are unsurprisingly excluded. +If the DirectorInterface contains a method with a matching signature to a virtual method of the C++ class then the virtual C++ method will be overwritten with the Go method. As Go doesn't support protected -methods all overriden protected virtual C++ methods will be public in Go. +methods all overridden protected virtual C++ methods will be public in Go.

      @@ -843,7 +857,7 @@ the Go methods.

      -

      23.4.7.5 Call base methods

      +

      24.4.7.5 Call base methods

      @@ -880,7 +894,7 @@ be found in the end of the guide.

      -

      23.4.7.6 Subclass via embedding

      +

      24.4.7.6 Subclass via embedding

      @@ -941,14 +955,14 @@ methods of the FooBarAbstract C++ class by means of embedding. The public FooBarGo interface type includes the FooBarAbstract interface and hence FooBarGo can be used as a drop in replacement for FooBarAbstract while the reverse isn't possible and would raise a -compile time error. Furthemore the constructor and destructor functions +compile time error. Furthermore the constructor and destructor functions NewFooBarGo and DeleteFooBarGo take care of all the director specifics and to the user the class appears as any other SWIG wrapped C++ class.

      -

      23.4.7.7 Memory management with runtime.SetFinalizer

      +

      24.4.7.7 Memory management with runtime.SetFinalizer

      @@ -1013,7 +1027,7 @@ before using runtime.SetFinalizer to know all of its gotchas.

      -

      23.4.7.8 Complete FooBarGo example class

      +

      24.4.7.8 Complete FooBarGo example class

      @@ -1054,7 +1068,7 @@ type overwrittenMethodsOnFooBarAbstract struct { fb FooBarAbstract // If additional constructor arguments have been given they are typically - // stored here so that the overriden methods can use them. + // stored here so that the overridden methods can use them. } func (om *overwrittenMethodsOnFooBarAbstract) Foo() string { @@ -1081,7 +1095,7 @@ func NewFooBarGo() FooBarGo { // The memory of the FooBarAbstract director object instance can be // automatically freed once the FooBarGo instance is garbage collected by // uncommenting the following line. Please make sure to understand the - // runtime.SetFinalizer specific gotchas before doing this. Furthemore + // runtime.SetFinalizer specific gotchas before doing this. Furthermore // DeleteFooBarGo should be deleted if a finalizer is in use or the fooBarGo // struct needs additional data to prevent double deletion. // runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract) @@ -1142,7 +1156,7 @@ SWIG/Examples/go/director/.

      -

      23.4.8 Default Go primitive type mappings

      +

      24.4.8 Default Go primitive type mappings

      @@ -1249,7 +1263,7 @@ that typemap, or add new values, to control how C/C++ types are mapped into Go types.

      -

      23.4.9 Output arguments

      +

      24.4.9 Output arguments

      Because of limitations in the way output arguments are processed in swig, @@ -1289,7 +1303,7 @@ fraction := modulename.Modf(5.0, ptr)

    Since this is ugly, you may want to wrap the swig-generated API with -some additional functions written in go that +some additional functions written in go that hide the ugly details.

    There are no char *OUTPUT typemaps. However you can @@ -1302,7 +1316,7 @@ void f(char *output); -

    23.4.10 Adding additional go code

    +

    24.4.10 Adding additional go code

    Often the APIs generated by swig are not very natural in go, especially if @@ -1397,7 +1411,7 @@ func bar() { -

    23.4.11 Go typemaps

    +

    24.4.11 Go typemaps

    diff --git a/Doc/Manual/Guile.html b/Doc/Manual/Guile.html index f30e139e5..31d822599 100644 --- a/Doc/Manual/Guile.html +++ b/Doc/Manual/Guile.html @@ -8,7 +8,7 @@ -

    24 SWIG and Guile

    +

    25 SWIG and Guile

    -
  • Exception Handling -
  • Procedure documentation -
  • Procedures with setters -
  • GOOPS Proxy Classes +
  • Native Guile pointers +
  • Exception Handling +
  • Procedure documentation +
  • Procedures with setters +
  • GOOPS Proxy Classes @@ -47,7 +48,7 @@

    This section details guile-specific support in SWIG. -

    24.1 Supported Guile Versions

    +

    25.1 Supported Guile Versions

    @@ -61,7 +62,7 @@ improved performance. This is currently not tested with swig so your mileage may vary. To be safe set environment variable GUILE_AUTO_COMPILE to 0 when using swig generated guile code. -

    24.2 Meaning of "Module"

    +

    25.2 Meaning of "Module"

    @@ -69,7 +70,7 @@ There are three different concepts of "module" involved, defined separately for SWIG, Guile, and Libtool. To avoid horrible confusion, we explicitly prefix the context, e.g., "guile-module". -

    24.3 Old GH Guile API

    +

    25.3 Old GH Guile API

    Guile 1.8 and older could be interfaced using two different api's, the SCM @@ -80,7 +81,7 @@ or the GH API. The GH interface to guile is deprecated. Read more about why in version of SWIG that can still generate guile GH wrapper code is 2.0.9. Please use that version if you really need the GH wrapper code. -

    24.4 Linkage

    +

    25.4 Linkage

    @@ -88,7 +89,7 @@ Guile support is complicated by a lack of user community cohesiveness, which manifests in multiple shared-library usage conventions. A set of policies implementing a usage convention is called a linkage. -

    24.4.1 Simple Linkage

    +

    25.4.1 Simple Linkage

    @@ -193,7 +194,7 @@ placed between the define-module form and the SWIG_init via a preprocessor define to avoid symbol clashes. For this case, however, passive linkage is available. -

    24.4.2 Passive Linkage

    +

    25.4.2 Passive Linkage

    Passive linkage is just like simple linkage, but it generates an @@ -203,7 +204,7 @@ package name (see below).

    You should use passive linkage rather than simple linkage when you are using multiple modules. -

    24.4.3 Native Guile Module Linkage

    +

    25.4.3 Native Guile Module Linkage

    SWIG can also generate wrapper code that does all the Guile module @@ -244,7 +245,7 @@ Newer Guile versions have a shorthand procedure for this: -

    24.4.4 Old Auto-Loading Guile Module Linkage

    +

    25.4.4 Old Auto-Loading Guile Module Linkage

    Guile used to support an autoloading facility for object-code @@ -270,7 +271,7 @@ option, SWIG generates an exported module initialization function with an appropriate name. -

    24.4.5 Hobbit4D Linkage

    +

    25.4.5 Hobbit4D Linkage

    @@ -295,7 +296,7 @@ my/lib/libfoo.so.X.Y.Z and friends. This scheme is still very experimental; the (hobbit4d link) conventions are not well understood.

    -

    24.5 Underscore Folding

    +

    25.5 Underscore Folding

    @@ -307,7 +308,7 @@ complained so far. %rename to specify the Guile name of the wrapped functions and variables (see CHANGES). -

    24.6 Typemaps

    +

    25.6 Typemaps

    @@ -399,7 +400,7 @@ constant will appear as a scheme variable. See Features and the %feature directive for info on how to apply the %feature.

    -

    24.7 Representation of pointers as smobs

    +

    25.7 Representation of pointers as smobs

    @@ -420,7 +421,7 @@ representing the expected pointer type. See also If the Scheme object passed was not a SWIG smob representing a compatible pointer, a wrong-type-arg exception is raised. -

    24.7.1 Smobs

    +

    25.7.1 Smobs

    @@ -439,7 +440,7 @@ structure describing this type. If a generated GOOPS module has been loaded, sm the corresponding GOOPS class.

    -

    24.7.2 Garbage Collection

    +

    25.7.2 Garbage Collection

    Garbage collection is a feature of Guile since version 1.6. As SWIG now requires Guile > 1.8, @@ -453,7 +454,14 @@ is exactly like described in 24.8 Exception Handling +

    25.8 Native Guile pointers

    + + +

    +In addition to SWIG smob pointers, Guile's native pointer type are accepted as arguments to wrapped SWIG functions. This can be useful for passing pointers to bytevector data to wrapped functions. +

    + +

    25.9 Exception Handling

    @@ -479,7 +487,7 @@ mapping: The default when not specified here is to use "swig-error". See Lib/exception.i for details. -

    24.9 Procedure documentation

    +

    25.10 Procedure documentation

    If invoked with the command-line option -procdoc @@ -514,7 +522,7 @@ like this: typemap argument doc. See Lib/guile/typemaps.i for details. -

    24.10 Procedures with setters

    +

    25.11 Procedures with setters

    For global variables, SWIG creates a single wrapper procedure @@ -542,7 +550,7 @@ struct members, the procedures (struct-member-get pointer) and (struct-member-set pointer value) are not generated. -

    24.11 GOOPS Proxy Classes

    +

    25.12 GOOPS Proxy Classes

    SWIG can also generate classes and generic functions for use with @@ -688,7 +696,7 @@ Notice that <Foo> is used before it is defined. The fix is to just put th %import "foo.h" before the %inline block.

    -

    24.11.1 Naming Issues

    +

    25.12.1 Naming Issues

    As you can see in the example above, there are potential naming conflicts. The default exported @@ -725,7 +733,7 @@ guile-modules. For example,

    (use-modules ((Test) #:renamer (symbol-prefix-proc 'goops:))) -

    24.11.2 Linking

    +

    25.12.2 Linking

    The guile-modules generated above all need to be linked together. GOOPS support requires diff --git a/Doc/Manual/Introduction.html b/Doc/Manual/Introduction.html index 1c29f4760..8d161b73d 100644 --- a/Doc/Manual/Introduction.html +++ b/Doc/Manual/Introduction.html @@ -13,6 +13,11 @@

    • What is SWIG?
    • Why use SWIG? +
    • Target languages +
    • A SWIG example
      • SWIG interface file @@ -144,7 +149,79 @@ it provides a wide variety of customization features that let you change almost every aspect of the language bindings. This is the main reason why SWIG has such a large user manual ;-). -

        2.3 A SWIG example

        +

        2.3 Target languages

        + + +

        +SWIG in essence is a tool to generate code for making C/C++ code available to various other programming languages. +These higher level programming languages are the target languages for the SWIG code generator and C or C++ are the input languages. +A single target language must be specified when SWIG is run. +This results in generating code for C/C++ and the specified target language to interface with each other. +SWIG can be invoked multiple times, but with a different target language specified on each invocation. +This ability to interface C/C++ to many different target languages is one of SWIG's core strengths and features. +

        + +

        +SWIG is very broadly composed of two components. +A core component creates a parse tree from the input ISO C/C++ and SWIG directives (extensions to the C/C++ standards). +The parse tree is then passed to a second component, one of the target language modules for generating code specific to a higher level language. +SWIG supports many different target languages. +These target languages are given a status of either Supported or Experimental. +This status is provided to indicate the level of maturity to expect when using a particular target language as not all target languages are fully developed. +

        + +

        +The second part of the SWIG documentation contains a chapter for each target level language. +Each chapter will state the status (Supported or Experimental) for that language. +

        + +

        2.3.1 Supported status

        + + +

        +A target language is given the 'Supported' status when +

        + +
          +
        • It is in a mature, well functioning state.
        • +
        • It has its own comprehensive chapter in the documentation.
        • +
        • It passes all of the main SWIG test-suite and has a range of working examples.
        • +
        • It supports the vast majority of SWIG features.
        • +
        • It provides strong backwards compatibility between releases.
        • +
        + +

        +The above is a short summary and further details are outlined in the Supported status section in the Extending chapter. +The good news is that all the well-known and most popular languages have this status. +

        + +

        2.3.2 Experimental status

        + + +

        +A target language is given the 'Experimental' status when +

        + +
          +
        • It is of sub-standard quality, failing to meet the above 'Supported' status.
        • +
        • It is somewhere between the mid to mature stage of development.
        • +
        • It does not guarantee any backwards compatibility between releases.
        • +
        • It is in need of help to finish development.
        • +
        + +

        +Anyone using an experimental target language is strongly urged to assist with development of the target language module if they wish to use it. +

        +

        +SWIG displays a warning when an experimental target language is used in order to set expectations and emphasize the experimental status of the target language. +The usual warning suppression techniques can be used if required. +

        + +

        +The above is a short summary and further details are outlined in the Experimental status section in the Extending chapter. +

        + +

        2.4 A SWIG example

        @@ -155,7 +232,7 @@ following C code:

         /* File : example.c */
         
        -double  My_variable  = 3.0;
        +double My_variable = 3.0;
         
         /* Compute factorial of n */
         int fact(int n) {
        @@ -177,7 +254,7 @@ variable My_variable from Tcl.  You start by making a SWIG
         interface file as shown below (by convention, these files carry a .i
         suffix) :
         
        -

        2.3.1 SWIG interface file

        +

        2.4.1 SWIG interface file

        @@ -196,13 +273,13 @@ extern int    my_mod(int n, int m);
         

        -The interface file contains ANSI C function prototypes and variable +The interface file contains ISO C function prototypes and variable declarations. The %module directive defines the name of the module that will be created by SWIG. The %{ %} block provides a location for inserting additional code, such as C header files or additional C declarations, into the generated C wrapper code. -

        2.3.2 The swig command

        +

        2.4.2 The swig command

        @@ -235,7 +312,7 @@ and variables declared in the SWIG interface. A look at the file example_wrap.c reveals a hideous mess. However, you almost never need to worry about it. -

        2.3.3 Building a Perl5 module

        +

        2.4.3 Building a Perl5 module

        @@ -251,7 +328,7 @@ unix > ld -G example.o example_wrap.o -o example.so # This is for Sola unix > perl5.003 use example; print example::fact(4), "\n"; -print example::my_mod(23,7), "\n"; +print example::my_mod(23, 7), "\n"; print $example::My_variable + 4.5, "\n"; <ctrl-d> 24 @@ -261,7 +338,7 @@ unix >

        -

        2.3.4 Building a Python module

        +

        2.4.4 Building a Python module

        @@ -279,13 +356,13 @@ Type "copyright", "credits" or "license" for more information. >>> import example >>> example.fact(4) 24 ->>> example.my_mod(23,7) +>>> example.my_mod(23, 7) 2 >>> example.cvar.My_variable + 4.5 7.5 -

        2.3.5 Shortcuts

        +

        2.4.5 Shortcuts

        @@ -303,7 +380,7 @@ unix > ld -G example.o example_wrap.o -o example.so unix > perl5.003 use example; print example::fact(4), "\n"; -print example::my_mod(23,7), "\n"; +print example::my_mod(23, 7), "\n"; print $example::My_variable + 4.5, "\n"; <ctrl-d> 24 @@ -311,7 +388,7 @@ print $example::My_variable + 4.5, "\n"; 7.5 -

        2.4 Supported C/C++ language features

        +

        2.5 Supported C/C++ language features

        @@ -323,7 +400,7 @@ major features include:

        • Full C99 preprocessing. -
        • All ANSI C and C++ datatypes. +
        • All ISO C and C++ datatypes.
        • Functions, variables, and constants.
        • Classes.
        • Single and multiple inheritance. @@ -336,7 +413,9 @@ major features include:

        -Most of C++11 is also supported. Details are in the C++11 section. +Most of C++11 is also supported. Details are in the C++11 chapter. +C++14 support is covered in the C++14 chapter. +C++17 support is covered in the C++17 chapter.

        @@ -350,7 +429,7 @@ wrapping simple C++ code. In fact, SWIG is able to handle C++ code that stresses the very limits of many C++ compilers. -

        2.5 Non-intrusive interface building

        +

        2.6 Non-intrusive interface building

        @@ -362,7 +441,7 @@ interface and reuse the code in other applications. It is also possible to support different types of interfaces depending on the application.

        -

        2.6 Incorporating SWIG into a build system

        +

        2.7 Incorporating SWIG into a build system

        @@ -385,13 +464,13 @@ for further information on this and other Autoconf macros.

        -There is growing support for SWIG in some build tools, for example CMake +There is growing support for SWIG in some build tools, for example CMake is a cross-platform, open-source build manager with built in support for SWIG. CMake can detect the SWIG executable and many of the target language libraries for linking against. CMake knows how to build shared libraries and loadable modules on many different operating systems. This allows easy cross platform SWIG development. It can also generate the custom commands necessary for driving SWIG from IDEs and makefiles. All of this can be done from a single cross platform input file. -The following example is a CMake input file for creating a python wrapper for the SWIG interface file, example.i: +The following example is a CMake input file for creating a Python wrapper for the SWIG interface file, example.i:

        @@ -420,7 +499,7 @@ which will invoke SWIG and compile the generated C++ files into _example.so (UNI
         For other target languages on Windows a dll, instead of a .pyd file, is usually generated.
         

        -

        2.7 Hands off code generation

        +

        2.8 Hands off code generation

        @@ -433,7 +512,7 @@ it allows others to forget about the low-level implementation details.

        -

        2.8 SWIG and freedom

        +

        2.9 SWIG and freedom

        @@ -452,7 +531,7 @@ to work with complicated and unusual C/C++ applications. Ironically, the freedom that SWIG provides is countered by an extremely conservative approach to code generation. At its core, SWIG tries to distill even the most advanced C++ code down to a small -well-defined set of interface building techniques based on ANSI C +well-defined set of interface building techniques based on ISO C programming. Because of this, you will find that SWIG interfaces can be easily compiled by virtually every C/C++ compiler and that they can be used on any platform. Again, this is an important part of staying out diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index 20ffb1a91..db5f041e4 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -6,7 +6,7 @@ -

        25 SWIG and Java

        +

        26 SWIG and Java

      • Accessing protected members
      • Common customization features @@ -163,7 +167,7 @@ It covers most SWIG features, but certain low-level details are covered in less

        -

        25.1 Overview

        +

        26.1 Overview

        @@ -198,7 +202,7 @@ Various customisation tips and techniques using SWIG directives are covered. The latter sections cover the advanced techniques of using typemaps for complete control of the wrapping process.

        -

        25.2 Preliminaries

        +

        26.2 Preliminaries

        @@ -218,7 +222,7 @@ This is the commonly used method to load JNI code so your system will more than Android uses Java JNI and also works with SWIG. Please read the Android chapter in conjunction with this one if you are targeting Android.

        -

        25.2.1 Running SWIG

        +

        26.2.1 Running SWIG

        @@ -277,11 +281,11 @@ The following sections have further practical examples and details on how you mi compiling and using the generated files.

        -

        25.2.2 Additional Commandline Options

        +

        26.2.2 Additional Commandline Options

        -The following table list the additional commandline options available for the Java module. They can also be seen by using: +The following table lists the additional commandline options available for the Java module. They can also be seen by using:

        @@ -314,7 +318,7 @@ swig -java -help
         Their use will become clearer by the time you have finished reading this section on SWIG and Java.
         

        -

        25.2.3 Getting the right header files

        +

        26.2.3 Getting the right header files

        @@ -329,7 +333,7 @@ They are usually in directories like this:

        The exact location may vary on your machine, but the above locations are typical.

        -

        25.2.4 Compiling a dynamic module

        +

        26.2.4 Compiling a dynamic module

        @@ -349,7 +353,7 @@ However, SWIG tries to guess the right options when it is installed. Therefore, you may want to start with one of the examples in the Examples/java directory. If that doesn't work, you will need to read the man-pages for your compiler and linker to get the right set of options. You might also -check the SWIG Wiki for +check the SWIG Wiki for additional information.

        @@ -364,7 +368,7 @@ The name of the shared library output file is important. If the name of your SWIG module is "example", the name of the corresponding shared library file should be "libexample.so" (or equivalent depending on your machine, see Dynamic linking problems for more information). The name of the module is specified using the %module directive or -module command line option.

        -

        25.2.5 Using your module

        +

        26.2.5 Using your module

        @@ -399,7 +403,7 @@ $ If it doesn't work have a look at the following section which discusses problems loading the shared library.

        -

        25.2.6 Dynamic linking problems

        +

        26.2.6 Dynamic linking problems

        @@ -473,7 +477,7 @@ Exception in thread "main" java.lang.UnsatisfiedLinkError: exampleJNI.gcd(II)I

        where gcd is the missing JNI function that SWIG generated into the wrapper file. Also make sure you pass all of the required libraries to the linker. -The java -verbose:jni commandline switch is also a great way to get more information on unresolved symbols. +The java -verbose:jni commandline option is also a great way to get more information on unresolved symbols. One last piece of advice is to beware of the common faux pas of having more than one native library version in your path.

        @@ -481,12 +485,12 @@ One last piece of advice is to beware of the common faux pas of having more than In summary, ensure that you are using the correct C/C++ compiler and linker combination and options for successful native library loading. If you are using the examples that ship with SWIG, then the Examples/Makefile must have these set up correctly for your system. The SWIG installation package makes a best attempt at getting these correct but does not get it right 100% of the time. -The SWIG Wiki also has some settings for commonly used compiler and operating system combinations. +The SWIG Wiki also has some settings for commonly used compiler and operating system combinations. The following section also contains some C++ specific linking problems and solutions.

        -

        25.2.7 Compilation problems and compiling with C++

        +

        26.2.7 Compilation problems and compiling with C++

        @@ -538,7 +542,7 @@ Finally make sure the version of JDK header files matches the version of Java th

        -

        25.2.8 Building on Windows

        +

        26.2.8 Building on Windows

        @@ -547,7 +551,7 @@ You will want to produce a DLL that can be loaded by the Java Virtual Machine. This section covers the process of using SWIG with Microsoft Visual C++ 6 although the procedure may be similar with other compilers. In order for everything to work, you will need to have a JDK installed on your machine in order to read the JNI header files.

        -

        25.2.8.1 Running SWIG from Visual Studio

        +

        26.2.8.1 Running SWIG from Visual Studio

        @@ -563,7 +567,7 @@ Don't worry if the wrapper file doesn't exist yet--Visual Studio will keep a ref

      • Enter "SWIG" in the description field.
      • Enter "swig -java -o $(ProjDir)\$(InputName)_wrap.c $(InputPath)" in the "Build command(s) field"
      • Enter "$(ProjDir)\$(InputName)_wrap.c" in the "Output files(s) field". -
      • Next, select the settings for the entire project and go to C/C++ tab and select the Preprocessor category . Add the include directories to the JNI header files under "Additional include directories", eg "C:\jdk1.3\include,C:\jdk1.3\include\win32". +
      • Next, select the settings for the entire project and go to C/C++ tab and select the Preprocessor category. Add the include directories to the JNI header files under "Additional include directories", eg "C:\jdk1.3\include, C:\jdk1.3\include\win32".
      • Next, select the settings for the entire project and go to Link tab and select the General category. Set the name of the output file to match the name of your Java module (ie. example.dll).
      • Next, select the example.c and example_wrap.c files and go to the C/C++ tab and select the Precompiled Headers tab in the project settings. Disabling precompiled headers for these files will overcome any precompiled header errors while building.
      • Finally, add the java compilation as a post build rule in the Post-build step tab in project settings, eg, "c:\jdk1.3\bin\javac *.java" @@ -586,7 +590,7 @@ To run the native code in the DLL (example.dll), make sure that it is in your pa If the library fails to load have a look at Dynamic linking problems.

        -

        25.2.8.2 Using NMAKE

        +

        26.2.8.2 Using NMAKE

        @@ -641,11 +645,11 @@ java::

        To build the DLL and compile the java code, run NMAKE (you may need to run vcvars32 first). This is a pretty simplistic Makefile, but hopefully its enough to get you started. -Of course you may want to make changes for it to work for C++ by adding in the -c++ command line switch for swig and replacing .c with .cxx. +Of course you may want to make changes for it to work for C++ by adding in the -c++ command line option for swig and replacing .c with .cxx.

        -

        25.3 A tour of basic C/C++ wrapping

        +

        26.3 A tour of basic C/C++ wrapping

        @@ -655,7 +659,7 @@ variables are wrapped with JavaBean type getters and setters and so forth. This section briefly covers the essential aspects of this wrapping.

        -

        25.3.1 Modules, packages and generated Java classes

        +

        26.3.1 Modules, packages and generated Java classes

        @@ -691,7 +695,7 @@ swig -java -package com.bloggs.swig -outdir com/bloggs/swig example.i SWIG won't create the directory, so make sure it exists beforehand.

        -

        25.3.2 Functions

        +

        26.3.2 Functions

        @@ -725,7 +729,7 @@ System.out.println(example.fact(4));

      • -

        25.3.3 Global variables

        +

        26.3.3 Global variables

        @@ -812,7 +816,7 @@ extern char *path; // Read-only (due to %immutable)

      • -

        25.3.4 Constants

        +

        26.3.4 Constants

        @@ -952,7 +956,7 @@ Or if you decide this practice isn't so bad and your own class implements ex

        -

        25.3.5 Enumerations

        +

        26.3.5 Enumerations

        @@ -966,7 +970,7 @@ The final two approaches use simple integers for each enum item. Before looking at the various approaches for wrapping named C/C++ enums, anonymous enums are considered.

        -

        25.3.5.1 Anonymous enums

        +

        26.3.5.1 Anonymous enums

        @@ -1029,7 +1033,7 @@ As in the case of constants, you can access them through either the module class

        -

        25.3.5.2 Typesafe enums

        +

        26.3.5.2 Typesafe enums

        @@ -1109,11 +1113,10 @@ Typesafe enums have their advantages over using plain integers in that they can However, there are limitations. For example, they cannot be used in switch statements and serialization is an issue. Please look at the following references for further information: - http://java.sun.com/developer/Books/shiftintojava/page1.html#replaceenums Replace Enums with Classes in Effective Java Programming on the Sun website, -Create enumerated constants in Java JavaWorld article, -Java Tip 133: More on typesafe enums and -Java Tip 122: Beware of Java typesafe enumerations JavaWorld tips. +Create enumerated constants in Java JavaWorld article, +Java Tip 133: More on typesafe enums and +Java Tip 122: Beware of Java typesafe enumerations JavaWorld tips.

        @@ -1123,7 +1126,7 @@ When upgrading to JDK 1.5 or later, proper Java enums could be used instead, wit The following section details proper Java enum generation.

        -

        25.3.5.3 Proper Java enums

        +

        26.3.5.3 Proper Java enums

        @@ -1176,7 +1179,7 @@ The additional support methods need not be generated if none of the enum items h Simpler Java enums for enums without initializers section.

        -

        25.3.5.4 Type unsafe enums

        +

        26.3.5.4 Type unsafe enums

        @@ -1224,7 +1227,7 @@ Note that unlike typesafe enums, this approach requires users to mostly use diff Thus the upgrade path to proper enums provided in JDK 1.5 is more painful.

        -

        25.3.5.5 Simple enums

        +

        26.3.5.5 Simple enums

        @@ -1243,7 +1246,7 @@ SWIG-1.3.21 and earlier versions wrapped all enums using this approach. The type unsafe approach is preferable to this one and this simple approach is only included for backwards compatibility with these earlier versions of SWIG.

        -

        25.3.6 Pointers

        +

        26.3.6 Pointers

        @@ -1267,7 +1270,7 @@ When wrapped, you will be able to use the functions in a natural way from Java.

        -SWIGTYPE_p_FILE f = example.fopen("junk","w");
        +SWIGTYPE_p_FILE f = example.fopen("junk", "w");
         example.fputs("Hello World\n", f);
         example.fclose(f);
         
        @@ -1309,16 +1312,16 @@ example: %inline %{ /* C-style cast */ Bar *FooToBar(Foo *f) { - return (Bar *) f; + return (Bar *) f; } /* C++-style cast */ Foo *BarToFoo(Bar *b) { - return dynamic_cast<Foo*>(b); + return dynamic_cast<Foo*>(b); } Foo *IncrFoo(Foo *f, int i) { - return f+i; + return f+i; } %}
        @@ -1331,7 +1334,7 @@ C-style cast may return a bogus result whereas as the C++-style cast will return a NULL pointer if the conversion can't be performed.

        -

        25.3.7 Structures

        +

        26.3.7 Structures

        @@ -1341,7 +1344,7 @@ member variables. For example,

         struct Vector {
        -  double x,y,z;
        +  double x, y, z;
         };
         
         
        @@ -1377,12 +1380,12 @@ can also be forced to be read-only using the %immutable directive. For
         struct Foo {
        -   ...
        -   %immutable;
        -   int x;        /* Read-only members */
        -   char *name;
        -   %mutable;
        -   ...
        +  ...
        +  %immutable;
        +  int x;        /* Read-only members */
        +  char *name;
        +  %mutable;
        +  ...
         };
         
        @@ -1403,7 +1406,7 @@ example, consider this:
         struct Bar {
        -    int  x[16];
        +  int  x[16];
         };
         
        @@ -1452,11 +1455,11 @@ pointer. For example, suppose you have two structures like this:
         struct Foo {
        -   int a;
        +  int a;
         };
         
         struct Bar {
        -   Foo f;
        +  Foo f;
         };
         
        @@ -1499,7 +1502,7 @@ x.setA(3); // Modify x.a - this is the same as b.f.a
        -

        25.3.8 C++ classes

        +

        26.3.8 C++ classes

        @@ -1544,8 +1547,8 @@ Static class members are unsurprisingly wrapped as static members of the Java cl

         class Spam {
         public:
        -   static void foo();
        -   static int bar;
        +  static void foo();
        +  static int bar;
         };
         
        @@ -1562,7 +1565,7 @@ int bar = Spam.getBar(); -

        25.3.9 C++ inheritance

        +

        26.3.9 C++ inheritance

        @@ -1623,7 +1626,7 @@ Note that Java does not support multiple inheritance so any multiple inheritance A warning is given when multiple inheritance is detected and only the first base class is used.

        -

        25.3.10 Pointers, references, arrays and pass by value

        +

        26.3.10 Pointers, references, arrays and pass by value

        @@ -1678,7 +1681,7 @@ to hold the result and a pointer is returned (Java will release this memory when the returned object's finalizer is run by the garbage collector).

        -

        25.3.10.1 Null pointers

        +

        26.3.10.1 Null pointers

        @@ -1702,7 +1705,7 @@ For spam1 and spam4 above the Java null gets translat The converse also occurs, that is, NULL pointers are translated into null Java objects when returned from a C/C++ function.

        -

        25.3.11 C++ overloaded functions

        +

        26.3.11 C++ overloaded functions

        @@ -1738,9 +1741,9 @@ Similarly, if you have a class like this,

         class Foo {
         public:
        -    Foo();
        -    Foo(const Foo &);
        -    ...
        +  Foo();
        +  Foo(const Foo &);
        +  ...
         };
         
        @@ -1817,7 +1820,7 @@ void spam(unsigned short); // Ignored -

        25.3.12 C++ default arguments

        +

        26.3.12 C++ default arguments

        @@ -1860,7 +1863,7 @@ Further details on default arguments and how to restore this approach are given

        -

        25.3.13 C++ namespaces

        +

        26.3.13 C++ namespaces

        @@ -1876,10 +1879,10 @@ submodules or packages. For example, if you have a file like this, %module example namespace foo { - int fact(int n); - struct Vector { - double x,y,z; - }; + int fact(int n); + struct Vector { + double x, y, z; + }; }; @@ -1907,11 +1910,11 @@ For example: %rename(Bar_spam) Bar::spam; namespace Foo { - int spam(); + int spam(); } namespace Bar { - int spam(); + int spam(); } @@ -1950,7 +1953,7 @@ If the resulting use of the nspace feature and hence packages results in a proxy you will need to open up the visibility for the pointer constructor and getCPtr method from the default 'protected' to 'public' with the SWIG_JAVABODY_PROXY macro. See Java code typemaps.

        -

        25.3.14 C++ templates

        +

        26.3.14 C++ templates

        @@ -1969,16 +1972,16 @@ For example: template<class T1, class T2> struct pair { - typedef T1 first_type; - typedef T2 second_type; - T1 first; - T2 second; - pair(); - pair(const T1&, const T2&); + typedef T1 first_type; + typedef T2 second_type; + T1 first; + T2 second; + pair(); + pair(const T1&, const T2&); ~pair(); }; -%template(pairii) pair<int,int>; +%template(pairii) pair<int, int>; @@ -1988,7 +1991,7 @@ In Java:

        -pairii p = new pairii(3,4);
        +pairii p = new pairii(3, 4);
         int first = p.getFirst();
         int second = p.getSecond();
         
        @@ -1999,10 +2002,10 @@ Obviously, there is more to template wrapping than shown in this example. More details can be found in the SWIG and C++ chapter.

        -

        25.3.15 C++ Smart Pointers

        +

        26.3.15 C++ Smart Pointers

        -

        25.3.15.1 The shared_ptr Smart Pointer

        +

        26.3.15.1 The shared_ptr Smart Pointer

        @@ -2013,7 +2016,7 @@ in the shared_ptr smart pointer -

        25.3.15.2 Generic Smart Pointers

        +

        26.3.15.2 Generic Smart Pointers

        @@ -2025,9 +2028,9 @@ that implements operator->() like this:

         template<class T> class SmartPtr {
        -   ...
        -   T *operator->();
        -   ...
        +  ...
        +  T *operator->();
        +  ...
         }
         
        @@ -2040,8 +2043,8 @@ Then, if you have a class like this,
         class Foo {
         public:
        -     int x;
        -     int bar();
        +  int x;
        +  int bar();
         };
         
        @@ -2097,7 +2100,7 @@ Foo f = p.__deref__(); // Returns underlying Foo * -

        25.4 Further details on the generated Java classes

        +

        26.4 Further details on the generated Java classes

        @@ -2112,7 +2115,7 @@ Finally enum classes are covered. First, the crucial intermediary JNI class is considered.

        -

        25.4.1 The intermediary JNI class

        +

        26.4.1 The intermediary JNI class

        @@ -2125,8 +2128,8 @@ have a global function and class like this

         class Foo {
         public:
        -     int x;
        -     int spam(int num, Foo* foo);
        +  int x;
        +  int spam(int num, Foo* foo);
         };
         void egg(Foo* chips);
         
        @@ -2140,19 +2143,19 @@ These procedural wrappers essentially perform the equivalent of this C++ code:
         Foo *new_Foo() {
        -    return new Foo();
        +  return new Foo();
         }
         void delete_Foo(Foo *f) {
        -    delete f;
        +  delete f;
         }
         int Foo_x_get(Foo *f) {
        -    return f->x;
        +  return f->x;
         }
         void Foo_x_set(Foo *f, int value) {
        -    f->x = value;
        +  f->x = value;
         }
         int Foo_spam(Foo *f, int num, Foo* foo) {
        -    return f->spam(num, foo);
        +  return f->spam(num, foo);
         }
         
        @@ -2232,7 +2235,7 @@ If name is the same as modulename then the module class name g from modulename to modulenameModule.

        -

        25.4.1.1 The intermediary JNI class pragmas

        +

        26.4.1.1 The intermediary JNI class pragmas

        @@ -2314,7 +2317,7 @@ For example, let's change the intermediary JNI class access to just the default All the methods in the intermediary JNI class will then not be callable outside of the package as the method modifiers have been changed from public access to default access. This is useful if you want to prevent users calling these low level functions.

        -

        25.4.2 The Java module class

        +

        26.4.2 The Java module class

        @@ -2345,7 +2348,7 @@ example.egg(new Foo()); The primary reason for having the module class wrapping the calls in the intermediary JNI class is to implement static type checking. In this case only a Foo can be passed to the egg function, whereas any long can be passed to the egg function in the intermediary JNI class.

        -

        25.4.2.1 The Java module class pragmas

        +

        26.4.2.1 The Java module class pragmas

        @@ -2396,7 +2399,7 @@ See The intermediary JNI class pragmas secti

        -

        25.4.3 Java proxy classes

        +

        26.4.3 Java proxy classes

        @@ -2472,7 +2475,7 @@ int y = f.spam(5, new Foo()); -

        25.4.3.1 Memory management

        +

        26.4.3.1 Memory management

        @@ -2494,10 +2497,10 @@ they came from. Therefore, the ownership is set to false. For example:

         class Foo {
         public:
        -    Foo();
        -    Foo bar1();
        -    Foo &bar2();
        -    Foo *bar2();
        +  Foo();
        +  Foo bar1();
        +  Foo &bar2();
        +  Foo *bar2();
         };
         
        @@ -2532,9 +2535,9 @@ change the ownership of an object. For instance, consider code like this:
         class Obj {};
         class Node {
        -   Obj *value;
        +  Obj *value;
         public:
        -   void set_value(Obj *v) { value = v; }
        +  void set_value(Obj *v) { value = v; }
         };
         
        @@ -2580,7 +2583,7 @@ However, you can tell the proxy class to manage the memory if you specify the @@ -2608,7 +2611,7 @@ Now add in the %newobject directive: class Obj {...}; class Factory { public: - static Obj *createObj() { return new Obj(); } + static Obj *createObj() { return new Obj(); } }; @@ -2634,7 +2637,7 @@ and

        -

        25.4.3.2 Inheritance

        +

        26.4.3.2 Inheritance

        @@ -2750,7 +2753,7 @@ However, true cross language polymorphism can be achieved using the 25.4.3.3 Proxy classes and garbage collection +

        26.4.3.3 Proxy classes and garbage collection

        @@ -2759,7 +2762,7 @@ The finalize() method calls delete() which frees any malloc'd The idea is for delete() to be called when you have finished with the C/C++ object. Ideally you need not call delete(), but rather leave it to the garbage collector to call it from the finalizer. When a program exits, the garbage collector does not guarantee to call all finalizers. -An insight into the reasoning behind this can be obtained from Hans Boehm's Destructors, Finalizers, and Synchronization paper. +An insight into the reasoning behind this can be obtained from Hans Boehm's Destructors, Finalizers, and Synchronization paper. Depending on what the finalizers do and which operating system you use, this may or may not be a problem.

        @@ -2783,7 +2786,7 @@ Call the System.runFinalizersOnExit(true) or Runtime.getRuntime().r This method is inherently unsafe. It may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock.

        In many cases you will be lucky and find that it works, but it is not to be advocated. -Have a look at Java web site and search for runFinalizersOnExit. +Have a look at Java web site and search for runFinalizersOnExit.

      • @@ -2833,7 +2836,7 @@ The section on Java typemaps details how to specify See the How to Handle Java Finalization's Memory-Retention Issues article for alternative approaches to managing memory by avoiding finalizers altogether.

        -

        25.4.3.4 The premature garbage collection prevention parameter for proxy class marshalling

        +

        26.4.3.4 The premature garbage collection prevention parameter for proxy class marshalling

        @@ -2955,7 +2958,7 @@ For example: Compatibility note: The generation of this additional parameter did not occur in versions prior to SWIG-1.3.30.

        -

        25.4.3.5 Single threaded applications and thread safety

        +

        26.4.3.5 Single threaded applications and thread safety

        @@ -3043,7 +3046,7 @@ for (int i=0; i<100000; i++) { -

        25.4.4 Type wrapper classes

        +

        26.4.4 Type wrapper classes

        @@ -3130,7 +3133,7 @@ public static void spam(SWIGTYPE_p_int x, SWIGTYPE_p_int y, int z) { ... } -

        25.4.5 Enum classes

        +

        26.4.5 Enum classes

        @@ -3139,7 +3142,7 @@ The Enumerations section discussed these but om The following sub-sections detail the various types of enum classes that can be generated.

        -

        25.4.5.1 Typesafe enum classes

        +

        26.4.5.1 Typesafe enum classes

        @@ -3223,7 +3226,7 @@ The swigValue method is used for marshalling in the other direction. The toString method is overridden so that the enum name is available.

        -

        25.4.5.2 Proper Java enum classes

        +

        26.4.5.2 Proper Java enum classes

        @@ -3301,7 +3304,7 @@ These needn't be generated if the enum being wrapped does not have any initializ Simpler Java enums for enums without initializers section describes how typemaps can be used to achieve this.

        -

        25.4.5.3 Type unsafe enum classes

        +

        26.4.5.3 Type unsafe enum classes

        @@ -3332,7 +3335,7 @@ public final class Beverage { -

        25.4.6 Interfaces

        +

        26.4.6 Interfaces

        @@ -3577,7 +3580,7 @@ typemap which is only used when a class is marked with the interface fe See Java code typemaps for details.

        -

        25.5 Cross language polymorphism using directors

        +

        26.5 Cross language polymorphism using directors

        @@ -3599,7 +3602,7 @@ The upshot is that C++ classes can be extended in Java and from C++ these extens Neither C++ code nor Java code needs to know where a particular method is implemented: the combination of proxy classes, director classes, and C wrapper functions transparently takes care of all the cross-language method routing.

        -

        25.5.1 Enabling directors

        +

        26.5.1 Enabling directors

        @@ -3625,7 +3628,7 @@ The %feature directive can be applied globally, to specific classes, and to spec // generate directors for all classes that have virtual methods %feature("director"); -// generate directors for all virtual methods in class Foo +// generate directors for the virtual methods in class Foo %feature("director") Foo; @@ -3643,7 +3646,7 @@ So for example,

        -will generate directors for all virtual methods of class Foo except bar(). +will generate directors for the virtual methods of class Foo except bar().

        @@ -3656,18 +3659,18 @@ In the following, class Bar will get a director class that handles the methods o %feature("director") Foo; class Foo { public: - virtual void one(); - virtual void two(); + virtual void one(); + virtual void two(); }; class Bar: public Foo { public: - virtual void three(); + virtual void three(); }; -

        25.5.2 Director classes

        +

        26.5.2 Director classes

        @@ -3679,7 +3682,8 @@ The director classes store a pointer to their underlying Java proxy classes.

        For simplicity let's ignore the Swig::Director class and refer to the original C++ class as the director's base class. By default, a director class extends all virtual methods in the inheritance chain of its base class (see the preceding section for how to modify this behavior). -Thus all virtual method calls, whether they originate in C++ or in Java via proxy classes, eventually end up in at the implementation in the director class. +Virtual methods that have a final specifier are unsurprisingly excluded. +Thus the virtual method calls, whether they originate in C++ or in Java via proxy classes, eventually end up in at the implementation in the director class. The job of the director methods is to route these method calls to the appropriate place in the inheritance chain. By "appropriate place" we mean the method that would have been called if the C++ base class and its Java derived classes were seamlessly integrated. That seamless integration is exactly what the director classes provide, transparently skipping over all the messy JNI glue code that binds the two languages together. @@ -3694,7 +3698,7 @@ If the correct implementation is in Java, the Java API is used to call the metho

        -

        25.5.3 Overhead and code bloat

        +

        26.5.3 Overhead and code bloat

        @@ -3712,7 +3716,7 @@ This situation can be optimized by selectively enabling director methods (using

        -

        25.5.4 Simple directors example

        +

        26.5.4 Simple directors example

        @@ -3745,12 +3749,10 @@ Naturally, the SWIG generated C++ code and the generated Java intermediary class

        -public class DirectorDerived extends DirectorBase {
        -  public DirectorDerived() {
        -  }
        -
        +class DirectorDerived extends DirectorBase {
        +  @Override
           public void upcall_method() {
        -    System.out.println("DirectorDerived::upcall_method() invoked.");
        +    System.out.println("DirectorDerived.upcall_method() invoked.");
           }
         }
         
        @@ -3773,11 +3775,11 @@ will result in the following being output:
        -DirectorDerived::upcall_method() invoked.
        +DirectorDerived.upcall_method() invoked.
         
        -

        25.5.5 Director threading issues

        +

        26.5.5 Director threading issues

        @@ -3797,7 +3799,7 @@ Macros can be defined on the commandline when compiling your C++ code, or altern

        -

        25.5.6 Director performance tuning

        +

        26.5.6 Director performance tuning

        @@ -3818,51 +3820,192 @@ However, if all director methods are expected to usually be overridden by Java s The disadvantage is that invocation of director methods from C++ when Java doesn't actually override the method will require an additional call up into Java and back to C++. As such, this option is only useful when overrides are extremely common and instantiation is frequent enough that its performance is critical.

        -

        25.5.7 Java exceptions from directors

        +

        26.5.7 Java exceptions from directors

        With directors routing method calls to Java, and proxies routing them to C++, the handling of exceptions is an important concern. -The default behavior from SWIG 3.0 -onwards is to convert the thrown Java exception into a SWIG defined -DirectorException C++ exception. -SWIG 2.0 and earlier versions didn't provide any mechanism to handle the Java director method exceptions in C++. +The default behavior for Java exceptions thrown in a director method overridden in Java is +to store the thrown Java exception into a SWIG defined +Swig::DirectorException C++ class exception in the C++ layer and then throw this C++ exception.

        -Converting Java exceptions into C++ exceptions can be done in two different ways using -the director:except feature. -In the simplest approach, a code block is attached to each director method to -handle the mapping of Java exceptions into C++ exceptions. +Of course, should this exception be thrown, your C++ code must catch it and handle it before returning back to Java. +The default generated code does not attempt to handle the C++ exception, but there is a simple way +to make this all work by catching the C++ exception and extracting the original Java exception by using %catches for Swig::DirectorException. +Consider the example shown earlier with a modification to the upcall_method Java method to throw a Java exception:

        -%feature("director:except") MyClass::method(int x) {
        -  jthrowable $error = jenv->ExceptionOccurred();
        -  if ($error) {
        -    jenv->ExceptionClear();
        -    if (Swig::ExceptionMatches(jenv, $error, "java/lang/IndexOutOfBoundsException"))
        -      throw std::out_of_range(Swig::JavaExceptionMessage(jenv, $error).message());
        -    if (Swig::ExceptionMatches(jenv, $error, "$packagepath/MyJavaException"))
        -      throw MyCppException(Swig::JavaExceptionMessage(jenv, $error).message());
        -    throw std::runtime_error("Unexpected exception thrown in MyClass::method");
        +class DirectorDerived extends DirectorBase {
        +  @Override
        +  public void upcall_method() {
        +    System.out.println("DirectorDerived.upcall_method() invoked.");
        +    throw new RuntimeException("There was a problem!");
           }
         }
        -
        -class MyClass {
        -  /** Throws either a std::out_of_range or MyCppException on error */
        -  void method(int x);
        -}
         

        -This approach allows a flexible mapping of Java exceptions thrown by director methods into -C++ exceptions expected by a C++ caller. There -need not be any C++ exception specifications on the C++ method. The -utility function Swig::ExceptionMatches +Now, by default, the JVM will abort when example.callup(director) is called as the C++ +Swig::DirectorException (storing the Java exception) is thrown and not handled by the callup method. +Needless to say this is not very user friendly and so the recommendation is to add the following +simple %catches directive before SWIG parses the callup function: +

        + +
        +
        +%catches(Swig::DirectorException) callup;
        +
        +
        + +

        +Or target all wrapped methods using: +

        + +
        +
        +%catches(Swig::DirectorException);
        +
        +
        + +

        +This tells SWIG to generate a C++ catch handler using some code from the throws typemap for Swig::DirectorException that SWIG supplies by default, see Exception handling with %catches. +This typemap code is written to simply catch the C++ Swig::DirectorException class and immediately +return to Java throwing the original Java exception that it has stored. +The net result is a stack trace containing the original Java exception including the location that the exception was thrown from. +

        + +
        +
        +DirectorDerived.upcall_method() invoked.
        +Exception in thread "main" java.lang.RuntimeException: There was a problem!
        +    at DirectorDerived.upcall_method(runme.java:4)
        +    at exampleJNI.SwigDirector_DirectorBase_upcall_method(exampleJNI.java:20)
        +    at exampleJNI.callup(Native Method)
        +    at example.callup(example.java:12)
        +    at runme.main(runme.java:21)
        +
        +
        + +

        +More on the Swig::DirectorException class can be found in the next section which details how to customize the handling of director exceptions. +

        + +

        26.5.7.1 Customizing director exceptions

        + + +

        +This section is for advanced customization of director exceptions. +The recommendation for most users is to use the simple %catches directive described above as it should be sufficient for most users needs. +

        + +

        +The conversion of Java exceptions into C++ exceptions can be customized in two different ways using +the director:except feature. +In the first approach, a code block is attached to each director method to +handle the mapping of Java exceptions into C++ exceptions. +The code block is generated just after the call up from the C++ director method into the overloaded method in Java. Its primary function is to check if a Java exception has been thrown and then handle it in C++. +The example below converts a +java.lang.IndexOutOfBoundsException into a C++ std::out_of_range exception and converts a +user's Java MyJavaException into a C++ MyCppException exception. +If the Java exception doesn't match either of these, a fallback std::runtime_error C++ exception is thrown. +

        + +
        +
        +%feature("director:except") MyClass::dirmethod(int x) {
        +  jthrowable $error = jenv->ExceptionOccurred();
        +  if ($error) {
        +    if (Swig::ExceptionMatches(jenv, $error, "java/lang/IndexOutOfBoundsException"))
        +      throw std::out_of_range(Swig::JavaExceptionMessage(jenv, $error).message());
        +    if (Swig::ExceptionMatches(jenv, $error, "$packagepath/MyJavaException"))
        +      throw MyCppException(Swig::JavaExceptionMessage(jenv, $error).message());
        +    throw std::runtime_error("Unexpected exception thrown in MyClass::dirmethod");
        +  }
        +}
        +
        +class MyClass {
        +public:
        +  /** Throws either a std::out_of_range or MyCppException on error */
        +  virtual void dirmethod(int x);
        +  virtual ~MyClass();
        +};
        +
        +
        + +

        +A few special variables are expanded within the director:except feature. +

        +
          +
        • The special variable $error is expanded into a unique variable name (swigerror) + and should be used for the assignment of the jthrowable exception that occurred.
        • +
        • The special variable $packagepath is + replaced by the outer package provided for SWIG generation by the -package option.
        • +
        • The special variable $directorthrowshandlers is not shown above, but is replaced + by applicable "directorthrows" typemap contents (covered later in this section).
        • +
        • The special variable $null is not shown above, but is replaced + by a suitable default constructed object for returning from the director method (or nothing if + the director method has a void return). +
        • +
        + +

        +Utility functions/classes in director.swg are provided to aid the exception conversion as follows: +

        + +
        +
        +namespace Swig {
        +
        +  // Helper method to determine if a Java throwable matches a particular Java class type
        +  // Note side effect of clearing any pending exceptions
        +  bool ExceptionMatches(JNIEnv *jenv, jthrowable throwable, const char *classname);
        +
        +  // Helper class to extract the exception message from a Java throwable
        +  class JavaExceptionMessage {
        +  public:
        +    JavaExceptionMessage(JNIEnv *jenv, jthrowable throwable);
        +
        +    // Return a C string of the exception message in the jthrowable passed in the constructor
        +    // If no message is available, null_string is return instead
        +    const char *message(const char *null_string = 
        +                        "Could not get exception message in JavaExceptionMessage") const;
        +  };
        +
        +  // C++ Exception class for handling Java exceptions thrown during a director method Java upcall
        +  class DirectorException : public std::exception {
        +  public:
        +
        +    // Construct exception from a Java throwable
        +    DirectorException(JNIEnv *jenv, jthrowable throwable);
        +
        +    // More general constructor for handling as a java.lang.RuntimeException
        +    DirectorException(const char *msg);
        +
        +    // Return exception message extracted from the Java throwable
        +    const char *what() const throw();
        +
        +    // Reconstruct and raise/throw the Java Exception that caused the DirectorException
        +    // Note that any error in the JNI exception handling results in a Java RuntimeException
        +    void throwException(JNIEnv *jenv) const;
        +
        +    // Create and throw the DirectorException
        +    static void raise(JNIEnv *jenv, jthrowable throwable) {
        +      throw DirectorException(jenv, throwable);
        +    }
        +  };
        +
        +}
        +
        +
        + +

        +The utility function Swig::ExceptionMatches and class Swig::JavaExceptionMessage are provided to simplify writing code for wrappers that use the director:except feature. The function Swig::ExceptionMatches matches the type of the @@ -3870,13 +4013,10 @@ function Swig::ExceptionMatches matches the type of the name, such as "java/lang/IOError". If the throwable class is the same type, or derives from the given type, Swig::ExceptionMatches will return true. Care must be taken to provide the correct fully qualified name, since for wrapped exceptions the -generated proxy class will have additional package qualification, depending on +generated proxy class will have an additional package qualification, depending on the '-package' argument and use of the nspace - feature. The special variable $error is expanded by SWIG into a unique variable name and -should be used for the -assignment of the exception that occurred. The special variable $packagepath is -replaced by the outer package provided for SWIG generation by the -package -option. The utility class Swig::JavaExceptionMessage is a holder + feature. +The utility class Swig::JavaExceptionMessage is a holder providing access to the message from the thrown Java exception. The message() method returns the exception message as a const char *, which is only valid during the lifetime of the holder. Any code using this message @@ -3884,20 +4024,27 @@ needs to copy it, for example into a std::string or a newly constructed C++ exce

        -Using the above approach to +Using the first approach above to write handlers for a large number of methods will require -repetitive duplication of the director:except feature code. -To mitigate this, an alternative approach is provided via typemaps in a -fashion analagous to -the "throws" typemap. The -"throws" typemap provides an approach to automatically map all the C++ +repetitive duplication of the director:except feature code +for each director method. +To mitigate this, a second approach is provided via typemaps in a +fashion analogous to +the "throws" typemap. +The "throws" typemap provides a way to map all the C++ exceptions listed in a method's defined exceptions (either from a C++ exception specification or a %catches feature) into Java exceptions. The "directorthrows" typemap provides the inverse mapping and should contain code to convert a suitably matching Java exception into a C++ exception. +Only use this typemap if you wish to write custom conversions of Java exceptions into C++ exceptions +and apply them to many different methods. +The default handling which uses the Swig::DirectorException class should otherwise meet your needs. +

        + +

        The example below converts a Java java.lang.IndexOutOfBoundsException exception -to the typemap's type, that is std::out_of_range: +to the typemap's type, that is a std::out_of_range C++ exception:

        @@ -3912,39 +4059,49 @@ to the typemap's type, that is std::out_of_range:
         

        The "directorthrows" typemap is then used in conjunction with the director:except feature if the $directorthrowshandlers special variable -is used in the feature code. Consider the following, which also happens to be the default: +is used in the code block. Consider the following, which also happens to be the default:

         %feature("director:except") %{
        -   jthrowable $error = jenv->ExceptionOccurred();
        -   if ($error) {
        -     jenv->ExceptionClear();
        -     $directorthrowshandlers
        -     throw Swig::DirectorException(jenv, $error);
        -   }
        +  jthrowable $error = jenv->ExceptionOccurred();
        +  if ($error) {
        +    $directorthrowshandlers
        +    Swig::DirectorException::raise(jenv, $error);
        +  }
         %}
         
        -

        The code generated using the director:except feature -replaces the $directorthrowshandlers special variable with the code in -the "directorthrows" typemaps, for each and every exception defined for the method. -The possible exceptions can be defined either with a C++ exception +

        +where Swig::DirectorException::raise is the helper method to throw a C++ Swig::DirectorException, see above. +The code generated from the director:except feature +has the $directorthrowshandlers special variable replaced with the code in +the relevant "directorthrows" typemaps, for each and every exception defined for the method. +The relevant exceptions can be defined either with a C++ exception specification or %catches as described for the "throws" typemap.

        -Consider the following director method: +Let's try and put all this together by considering the following director method:

        -  ...
        +struct X {
           virtual void doSomething(int index) throw (std::out_of_range);
           ...
        +};
        +
        +OR
        +
        +%catches(std::out_of_range) X::doSomething;
        +struct X {
        +  virtual void doSomething(int index);
        +  ...
        +};
         
        @@ -3957,12 +4114,10 @@ the resulting code generated in the director method after calling up to Java wil
         jthrowable swigerror = jenv->ExceptionOccurred();
         if (swigerror) {
        -  jenv->ExceptionClear();
           if (Swig::ExceptionMatches(jenv, swigerror, "java/lang/IndexOutOfBoundsException")) {
             throw std::out_of_range(Swig::JavaExceptionMessage(jenv, swigerror).message());
           }
        -  
        -  throw Swig::DirectorException(jenv, swigerror);
        +  Swig::DirectorException::raise(jenv, swigerror);
         }
         
        @@ -3970,7 +4125,7 @@ if (swigerror) {

        Note: Beware of using exception specifications as the SWIG director methods will be generated with the same exception specifications and if the -director method throws an exception that is not specified it is likely +director method throws an exception that is not specified in the exception specifications list it is likely to terminate your program. See the C++ standard for more details. Using the %catches feature instead to define the handled exceptions does not suffer this potential fate. @@ -3978,19 +4133,20 @@ this potential fate.

        Because the default code generation maps any unhandled Java exceptions to Swig::DirectorException, any director methods that have exception -specifications may cause program termination. To simply ignore -unexpected exceptions, the default handling can be changed with: +specifications may cause program termination as this exception class won't be in the exception specifications list. +You can avoid throwing Swig::DirectorException by changing the default handling for all methods by adding a director:except feature without any method name. +For example, you can just ignore them:

         %feature("director:except") %{
        -   jthrowable $error = jenv->ExceptionOccurred();
        -   if ($error) {
        -     jenv->ExceptionClear();
        -     $directorthrowshandlers
        -     return $null; // exception is ignored
        -   }
        +  jthrowable $error = jenv->ExceptionOccurred();
        +  if ($error) {
        +    $directorthrowshandlers
        +    jenv->ExceptionClear();
        +    return $null; // exception is ignored
        +  }
         %}
         
        @@ -3998,135 +4154,307 @@ unexpected exceptions, the default handling can be changed with:

        Alternatively an exception compatible with the existing director method exception specifications can be thrown. Assuming that all methods allow std::runtime_error to be thrown, -the return $null; could be changed to: +the return $null line above could be changed to:

        -   throw std::runtime_error(Swig::JavaExceptionMessage(jenv, $error).message());
        +  throw std::runtime_error(Swig::JavaExceptionMessage(jenv, $error).message());
         

        In more complex situations, a separate director:except feature -may need to be attached to specific methods. +may need to be attached to specific methods by providing a method name to the director:except feature.

        -

        Below is a complete example demonstrating the use -of the "directorthrows" typemaps. In this example, a -generic "directorthrows" typemap is appropriate for all three exceptions - all -take single string constructors. If the exceptions had different constructors, -it would be necessary to have separate typemaps for each exception type. +

        This is all no doubt quite hard to follow without seeing a full example and some code. +Below is a complete example demonstrating the use +of most of the exception customizations one can use, that is, +"directorthrows" and "throws" typemaps, %exception and %catches. +See the Exception handling with %exception and %javaexception +section for more on converting C++ exceptions to Java exceptions. +The example also has a user defined C++ exception class called MyNS::MyException and this is wrapped as a Java exception. +The director class being wrapped is MyClass and the director method is called MyClass::dirmethod. +A number of std::cout calls have been added to help understand code flow. +You can copy the code below into an interface file and run SWIG on it and examine the generated code. -

         %module(directors="1") example
         
         %{
        -  #include <string>
           #include <stdexcept>
        +  #include <iostream>
         %}
         
        -// Define exceptions in header section using std::runtime_error
        -%define DEFINE_EXCEPTION(NAME)
        -%{
        -  namespace MyNS {
        -    struct NAME : public std::runtime_error { NAME(const std::string &what) : runtime_error(what) {} };
        +// Generic catch handler for all wrapped methods
        +%exception %{
        +  try {
        +    $action
        +  } catch (const std::exception &e) {
        +    std::cout << "Generic std::exception catch handler" << std::endl;
        +    jclass clazz = jenv->FindClass("java/lang/RuntimeException");
        +    jenv->ThrowNew(clazz, e.what()); 
        +    return $null;
           }
         %}
        -%enddef
         
        -// Expose C++ exceptions as Java Exceptions by changing the Java base class and providing a getMessage()
        -%define DECLARE_EXCEPTION(NAME)
        -%typemap(javabase) MyNS::NAME "java.lang.Exception";
        -%rename(getMessage) MyNS::NAME::what;
        +// Expose C++ exception as a Java Exception by changing the Java base class and providing a getMessage()
        +%typemap(javabase) MyNS::MyException "java.lang.RuntimeException";
        +%rename(getMessage) MyNS::MyException::whatsup;
        +
        +%inline %{
         namespace MyNS {
        -  struct NAME {
        -    NAME(const std::string& what);
        -    const char * what();
        +  class MyException {
        +    std::string msg;
        +  public:
        +    MyException(const char *msg) : msg(msg) {}
        +    const char * whatsup() const { return msg.c_str(); }
           };
         }
        -%enddef
        -
        -DEFINE_EXCEPTION(ExceptionA)
        -DEFINE_EXCEPTION(ExceptionB)
        -DEFINE_EXCEPTION(Unexpected)
        -
        -// Mark three methods to map director thrown exceptions.
        -%feature("director:except") MyClass::meth1(int);
        -%feature("director:except") MyClass::meth2;
        -%feature("director:except") meth3;
        -
        -%typemap(directorthrows) MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected %{
        -  if (Swig::ExceptionMatches(jenv, $error, "$packagepath/$javaclassname"))
        -    throw $1_type(Swig::JavaExceptionMessage(jenv, $error).message());
         %}
         
        -DECLARE_EXCEPTION(ExceptionA)
        -DECLARE_EXCEPTION(ExceptionB)
        -DECLARE_EXCEPTION(Unexpected)
        +%typemap(directorthrows) MyNS::MyException %{
        +  if (Swig::ExceptionMatches(jenv, $error, "$packagepath/MyException")) {
        +    std::cout << "$1_type exception matched (directorthrows typemap)" << std::endl;
        +    throw $1_type(Swig::JavaExceptionMessage(jenv, $error).message());
        +  }
        +%}
         
        -%catches(MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected) MyClass::meth2();
        +%typemap(throws) MyNS::MyException %{
        +  std::cout << "$1_type caught (throws typemap)" << std::endl;
        +  jclass excep = jenv->FindClass("MyException");
        +  if (excep) {
        +    std::cout << "$1_type class found (throws typemap)" << std::endl;
        +    jenv->ThrowNew(excep, $1.whatsup());
        +  }
        +  return $null;
        +%}
         
        -%inline {
        -  class MyClass {
        -  public:
        -    virtual void meth1(int x) throw(MyNS::ExceptionA, MyNS::ExceptionB) = 0;
        -    virtual void meth2() = 0;   /* throws MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected */
        -    virtual void meth3(float x) throw(MyNS::Unexpected) = 0;
        -    virtual ~MyClass() {}
        -  };
        +// These are the exceptions that the director method MyClass::dirmethod will have catch handlers for.
        +// Note that this is also a virtual method / director method and the C++ exceptions listed can be
        +// thrown after converting them from Java exceptions.
        +%catches(MyNS::MyException, Swig::DirectorException) MyClass::dirmethod;
        +
        +// These are the exceptions that call_dirmethod C++ wrapper will have catch handlers for.
        +// Note that this is not a virtual method, hence not a director method.
        +%catches(MyNS::MyException, Swig::DirectorException) call_dirmethod;
        +
        +%feature("director") MyClass;
        +
        +%feature("director:except") MyClass::dirmethod(int x) {
        +  jthrowable $error = jenv->ExceptionOccurred();
        +  if ($error) {
        +    std::cout << "Upcall finished, an exception was thrown in Java" << std::endl;
        +    $directorthrowshandlers
        +    std::cout << "Upcall finished, no exception conversion, throwing DirectorException" << std::endl;
        +    Swig::DirectorException::raise(jenv, $error);
        +  }
         }
        +
        +%inline %{
        +class MyClass {
        +public:
        +  /** Throws either a std::out_of_range or MyException on error */
        +  virtual void dirmethod(int x) {
        +    if (x <= 0)
        +      throw std::out_of_range("MyClass::dirmethod index is out of range");
        +    else if (x == 1)
        +      throw MyNS::MyException("MyClass::dirmethod some problem!");
        +  }
        +  virtual ~MyClass() {}
        +  static void call_dirmethod(MyClass& c, int x) {
        +    return c.dirmethod(x);
        +  }
        +};
        +%}
         

        -In this case the three different "directorthrows" typemaps will be used -to generate the three different exception handlers for -meth1, meth2 and meth3. The generated -handlers will have "if" blocks for each exception type specified, in -the exception specification or %catches feature. -

        - -

        Note that the "directorthrows" typemaps are important -only if it is important for the the exceptions passed through the C++ -layer to be mapped to distinct C++ exceptions. If director methods -are being called by C++ code that is itself wrapped in a -SWIG generated Java wrapper and access is always through this wrapper, -the default Swig::DirectorException class provides enough information -to reconstruct the original exception. In this case removing the -$directorthrowshandlers special variable from the -default director:except feature and simply always -throwing a Swig::DirectorException will achieve the desired result. -Along with this a generic exception feature is added to convert any -caught Swig::DirectorExceptions back into the underlying -Java exceptions via the Swig::DirectorException::raiseJavaException method, -as demonstrated with %javaexception below: +The generated code for the call_dirmethod wrapper contains the various exception handlers. +The outer exception handler is from the %exception directive and the others +are from the "throws" typemaps.

        -%javaexception("Exception") MyClass::myMethod %{
        +SWIGEXPORT void JNICALL Java_exampleJNI_MyClass_1call_1dirmethod(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) {
        +  ...
           try {
        -    $action
        -  } catch (Swig::DirectorException &e) {
        -    // raise/throw the Java exception that originally caused the DirectorException
        -    e.raiseJavaException(jenv);
        -    return $null;
        +    try {
        +      MyClass::call_dirmethod(*arg1,arg2);
        +    } catch(MyNS::MyException &_e) {
        +      std::cout << "MyNS::MyException caught (throws typemap)" << std::endl;
        +      jclass excep = jenv->FindClass("MyException");
        +      if (excep) {
        +        std::cout << "MyNS::MyException class found (throws typemap)" << std::endl;
        +        jenv->ThrowNew(excep, (&_e)->whatsup());
        +      }
        +      return ;
        +      
        +    } catch(Swig::DirectorException &_e) {
        +      (&_e)->throwException(jenv);
        +      return ; 
        +    }
        +  } catch (const std::exception &e) {
        +    std::cout << "Generic std::exception catch handler" << std::endl;
        +    jclass clazz = jenv->FindClass("java/lang/RuntimeException");
        +    jenv->ThrowNew(clazz, e.what()); 
        +    return ;
           }
        -%}
         

        -See the Exception handling with %exception and %javaexception -section for more on converting C++ exceptions to Java exceptions. +The director method calling up to Java contains the exception handling code from the "directorthrows" typemaps and director:except feature.

        -

        25.6 Accessing protected members

        +
        +
        +void SwigDirector_MyClass::dirmethod(int x) {
        +      ... [call up to Java using CallStaticVoidMethod]
        +      jthrowable swigerror = jenv->ExceptionOccurred();
        +      if (swigerror) {
        +        std::cout << "Upcall finished, an exception was thrown in Java" << std::endl;
        +        
        +        if (Swig::ExceptionMatches(jenv, swigerror, "MyException")) {
        +          std::cout << "MyNS::MyException exception matched (directorthrows typemap)" << std::endl;
        +          throw MyNS::MyException(Swig::JavaExceptionMessage(jenv, swigerror).message());
        +        }
        +        
        +        std::cout << "Upcall finished, no exception conversion, throwing DirectorException" << std::endl;
        +        Swig::DirectorException::raise(jenv, swigerror);
        +      }
        +
        +
        + +

        +Let's use the following Java class to override the director method. +

        + +
        +
        +class DerivedClass extends MyClass {
        +  @Override
        +  public void dirmethod(int x) {
        +    if (x < 0)
        +      throw new IndexOutOfBoundsException("Index is negative");
        +    else if (x == 0)
        +      throw new MyException("MyException: bad dirmethod");
        +  }
        +}
        +public class runme {
        +  public static void main(String argv[]) {
        +    System.loadLibrary("example");
        +    ... code snippets shown below ...
        +  }
        +}
        +
        +
        + +

        +Consider the output using the Java code in the four slightly different scenarios below. +

        + +

        +1. Non-director C++ class is used, thus, no upcall to a Java director method is made. +A std::out_of_range exception is thrown, which is derived from std::exception, +and hence caught by the generic exception handler in the call_dirmethod wrapper. +The Java code snippet and resulting output is: +

        + + +
        +
        +MyClass.call_dirmethod(new MyClass(), 0);
        +
        +
        + +
        +
        +Generic std::exception catch handler
        +Exception in thread "main" java.lang.RuntimeException: MyClass::dirmethod index is out of range
        +        at exampleJNI.MyClass_call_dirmethod(Native Method)
        +        at MyClass.call_dirmethod(MyClass.java:57)
        +        at runme.main(runme.java:14)
        +
        +
        + +

        +2. Non-director C++ class again but this time the MyNS::MyException class is thrown and caught: +

        + +
        +
        +MyClass.call_dirmethod(new MyClass(), 1);
        +
        +
        + +
        +
        +MyNS::MyException caught (throws typemap)
        +MyNS::MyException class found (throws typemap)
        +Exception in thread "main" MyException: MyClass::dirmethod some problem!
        +        at exampleJNI.MyClass_call_dirmethod(Native Method)
        +        at MyClass.call_dirmethod(MyClass.java:57)
        +        at runme.main(runme.java:15)
        +
        +
        + +

        +3. The DerivedClass director class is used so the upcall to Java occurs, but it throws +a Java MyException, which gets converted into a C++ MyNS::MyException, then caught and converted back +into a Java MyException: +

        + +
        +
        +MyClass.call_dirmethod(new DerivedClass(), 0);
        +
        +
        + +
        +
        +Upcall finished, an exception was thrown in Java
        +MyNS::MyException exception matched (directorthrows typemap)
        +MyNS::MyException caught (throws typemap)
        +MyNS::MyException class found (throws typemap)
        +Exception in thread "main" MyException: MyException: bad dirmethod
        +        at exampleJNI.MyClass_call_dirmethod(Native Method)
        +        at MyClass.call_dirmethod(MyClass.java:57)
        +        at runme.main(runme.java:16)
        +
        +
        + +

        +4. The director class is used again, but this time the director method throws a Java IndexOutOfBoundsException exception which is converted into a C++ Swig::DirectorException, thrown and caught again. +This time the original Java exception is extracted from the Swig::DirectorException and rethrown. +Note that this approach keeps the stack trace information of the original exception, so it has the exact location of where the IndexOutOfBoundsException exception was thrown. +This is arguably an improvement over the approach above that converts from a Java excepton to C++ exception and then back to a new Java exception, losing the location of the original exception. +

        + +
        +
        +MyClass.call_dirmethod(new DerivedClass(), -1);
        +
        +
        + +
        +
        +Upcall finished, an exception was thrown in Java
        +Upcall finished, no exception conversion, throwing DirectorException
        +Exception in thread "main" java.lang.IndexOutOfBoundsException: Index is negative
        +        at DerivedClass.dirmethod(runme.java:5)
        +        at exampleJNI.SwigDirector_MyClass_dirmethod(exampleJNI.java:23)
        +        at exampleJNI.MyClass_call_dirmethod(Native Method)
        +        at MyClass.call_dirmethod(MyClass.java:57)
        +        at runme.main(runme.java:17)
        +
        +
        + +

        26.6 Accessing protected members

        @@ -4222,7 +4550,7 @@ class MyProtectedBase extends ProtectedBase -

        25.7 Common customization features

        +

        26.7 Common customization features

        @@ -4234,7 +4562,7 @@ be awkward. This section describes some common SWIG features that are used to improve the interface to existing C/C++ code.

        -

        25.7.1 C/C++ helper functions

        +

        26.7.1 C/C++ helper functions

        @@ -4262,16 +4590,16 @@ functions. Just use the %inline directive. For example: %inline %{ /* Note: double[4][4] is equivalent to a pointer to an array double (*)[4] */ double (*new_mat44())[4] { - return (double (*)[4]) malloc(16*sizeof(double)); + return (double (*)[4]) malloc(16*sizeof(double)); } void free_mat44(double (*x)[4]) { - free(x); + free(x); } void mat44_set(double x[4][4], int i, int j, double v) { - x[i][j] = v; + x[i][j] = v; } double mat44_get(double x[4][4], int i, int j) { - return x[i][j]; + return x[i][j]; } %} @@ -4285,11 +4613,11 @@ From Java, you could then write code like this:

         Image im = new Image();
         SWIGTYPE_p_a_4__double a = example.new_mat44();
        -example.mat44_set(a,0,0,1.0);
        -example.mat44_set(a,1,1,1.0);
        -example.mat44_set(a,2,2,1.0);
        +example.mat44_set(a, 0, 0, 1.0);
        +example.mat44_set(a, 1, 1, 1.0);
        +example.mat44_set(a, 2, 2, 1.0);
         ...
        -example.set_transform(im,a);
        +example.set_transform(im, a);
         example.free_mat44(a);
         
        @@ -4300,7 +4628,7 @@ hard to implement. It is possible to improve on this using Java code, typemaps, customization features as covered in later sections, but sometimes helper functions are a quick and easy solution to difficult cases.

        -

        25.7.2 Class extension with %extend

        +

        26.7.2 Class extension with %extend

        @@ -4317,22 +4645,22 @@ Here is a simple example: %} struct Vector { - double x,y,z; + double x, y, z; }; %extend Vector { - char *toString() { - static char tmp[1024]; - sprintf(tmp,"Vector(%g,%g,%g)", $self->x,$self->y,$self->z); - return tmp; - } - Vector(double x, double y, double z) { - Vector *v = (Vector *) malloc(sizeof(Vector)); - v->x = x; - v->y = y; - v->z = z; - return v; - } + char *toString() { + static char tmp[1024]; + sprintf(tmp, "Vector(%g, %g, %g)", $self->x, $self->y, $self->z); + return tmp; + } + Vector(double x, double y, double z) { + Vector *v = (Vector *) malloc(sizeof(Vector)); + v->x = x; + v->y = y; + v->z = z; + return v; + } }; @@ -4343,7 +4671,7 @@ Now, in Java

        -Vector v = new Vector(2,3,4);
        +Vector v = new Vector(2, 3, 4);
         System.out.println(v);
         
        @@ -4354,7 +4682,7 @@ will display
        -Vector(2,3,4)
        +Vector(2, 3, 4)
         
        @@ -4363,7 +4691,144 @@ Vector(2,3,4) in any way---the extensions only show up in the Java interface.

        -

        25.7.3 Exception handling with %exception and %javaexception

        +

        26.7.3 Class extension with %proxycode

        + + +

        +The previous section described how to extend a wrapped class with C or C++ code. +This section describes how to extend a wrapped class with Java code instead of C/C++ code. +The %proxycode directive is used and is just a macro for %insert("proxycode"). +The Code insertion block section describes the %insert directive. +The section of code for insertion is "proxycode", that is, the Java proxy class. +This directive must hence only be used within the scope of a class, otherwise it is silently ignored. +There are two common ways to get the scope correct. +

        + +

        +The first is to use %proxycode inside a class that SWIG parses, for example a toString() method can be added to a C++ class using pure Java code. +A C++ header file can mix C++ and Java code inside the C++ class as follows: +

        + +
        +
        +// flag.h header file
        +class Flag {
        +  bool flag;
        +public:
        +  Flag(bool flag) : flag(flag) {}
        +  bool FetchFlag() { return flag; }
        +#if defined(SWIG)
        +%proxycode %{
        +  public String toString() {
        +    boolean flag = FetchFlag();
        +    return Boolean.toString(flag);
        +  }
        +%}
        +#endif
        +};
        +
        +
        + +

        +and wrapped using: +

        + +
        +
        +%{
        +#include "flag.h"
        +%}
        +%include "flag.h"
        +
        +
        + +

        +The second is to use %proxycode within %extend as everything within a %extend block is effectively within the scope of the class, for example: +

        + +
        +
        +// flag.h header file
        +class Flag {
        +  bool flag;
        +public:
        +  Flag(bool flag) : flag(flag) {}
        +  bool FetchFlag() { return flag; }
        +};
        +
        +
        + +

        +and wrapped using: +

        + +
        +
        +%{
        +#include "flag.h"
        +%}
        +%include "flag.h"
        +
        +%extend Flag {
        +#if defined(SWIG)
        +%proxycode %{
        +  public String toString() {
        +    boolean flag = FetchFlag();
        +    return Boolean.toString(flag);
        +  }
        +%}
        +#endif
        +}
        +
        +
        + +

        +There is some very limited support of typemaps within a %proxycode block. +A useful trick is to obtain the Java type for a given C/C++ type using the $typemap special macro. +The following C++ template demonstrates this: +

        + +
        +
        +%inline %{
        +template<typename T> struct Value {
        +  T value;
        +  Value(const T& val) : value(val) {}
        +};
        +%}
        +
        +%extend Value {
        +%proxycode %{
        +  public String toString() {
        +    // Note template type expansion is supported, so T is expanded to 'unsigned int' in this example
        +    // and $typemap(jstype, unsigned int) in turn is expanded to 'long'
        +    $typemap(jstype, T) val = getValue();
        +    return "$javaclassname value: " + val + " Java type: $typemap(jstype, T) JNI type: $typemap(jni, T)";
        +  }
        +%}
        +}
        +%template(ValueUnsignedInt) Value<unsigned int>;
        +
        +
        + +

        +The generated Java contains the expanded special variable and macro resulting in Java proxy code: +

        + +
        +
        +public class ValueUnsignedInt {
        +  ...
        +  public String toString() {
        +    long val = getValue();
        +    return "ValueUnsignedInt value: " + val + " Java type: long JNI type: jlong";
        +  }
        +
        +}
        +
        +
        + +

        26.7.4 Exception handling with %exception and %javaexception

        @@ -4451,18 +4916,18 @@ We can catch the C++ exception and rethrow it as a Java exception like this:

         %exception getitem {
           try {
        -     $action
        +    $action
           } catch (std::out_of_range &e) {
             jclass clazz = jenv->FindClass("java/lang/Exception");
             jenv->ThrowNew(clazz, "Range error");
             return $null;
        -   }
        +  }
         }
         
         class FooClass {
        -public:
        -     FooClass *getitem(int index);      // Might throw std::out_of_range exception
        -     ...
        +  public:
        +    FooClass *getitem(int index);      // Might throw std::out_of_range exception
        +    ...
         };
         
        @@ -4480,18 +4945,18 @@ See Clearing featur
         %javaexception("java.lang.Exception") getitem {
           try {
        -     $action
        +    $action
           } catch (std::out_of_range &e) {
             jclass clazz = jenv->FindClass("java/lang/Exception");
             jenv->ThrowNew(clazz, "Range error");
             return $null;
        -   }
        +  }
         }
         
         class FooClass {
         public:
        -     FooClass *getitem(int index);      // Might throw std::out_of_range exception
        -     ...
        +  FooClass *getitem(int index);      // Might throw std::out_of_range exception
        +  ...
         };
         
        @@ -4522,7 +4987,7 @@ to raise exceptions. See the
        SWIG Library ch The typemap example Handling C++ exception specifications as Java exceptions provides further exception handling capabilities.

        -

        25.7.4 Method access with %javamethodmodifiers

        +

        26.7.5 Method access with %javamethodmodifiers

        @@ -4548,7 +5013,7 @@ protected static void protect_me() { -

        25.8 Tips and techniques

        +

        26.8 Tips and techniques

        @@ -4558,7 +5023,7 @@ strings and arrays. This chapter discusses the common techniques for solving these problems.

        -

        25.8.1 Input and output parameters using primitive pointers and references

        +

        26.8.1 Input and output parameters using primitive pointers and references

        @@ -4569,7 +5034,7 @@ example:

         void add(int x, int y, int *result) {
        -   *result = x + y;
        +  *result = x + y;
         }
         
        @@ -4581,7 +5046,7 @@ or perhaps
         int sub(int *x, int *y) {
        -   return *x-*y;
        +  return *x-*y;
         }
         
        @@ -4606,10 +5071,10 @@ In Java, this allows you to pass simple values. For example:
        -int result = example.sub(7,4);
        +int result = example.sub(7, 4);
         System.out.println("7 - 4 = " + result);
         int[] sum = {0};
        -example.add(3,4,sum);
        +example.add(3, 4, sum);
         System.out.println("3 + 4 = " + sum[0]);
         
        @@ -4653,7 +5118,7 @@ If a function mutates one of its parameters like this,
         void negate(int *x) {
        -   *x = -(*x);
        +  *x = -(*x);
         }
         
        @@ -4732,7 +5197,7 @@ void foo(Bar *OUTPUT); will not have the intended effect since typemaps.i does not define an OUTPUT rule for Bar.

        -

        25.8.2 Simple pointers

        +

        26.8.2 Simple pointers

        @@ -4754,7 +5219,7 @@ extern void add(int x, int y, int *result);

        -The %pointer_functions(type,name) macro generates five helper functions that can be used to create, +The %pointer_functions(type, name) macro generates five helper functions that can be used to create, destroy, copy, assign, and dereference a pointer. In this case, the functions are as follows:

        @@ -4775,20 +5240,20 @@ In Java, you would use the functions like this:
         SWIGTYPE_p_int intPtr = example.new_intp();
        -example.add(3,4,intPtr);
        +example.add(3, 4, intPtr);
         int result = example.intp_value(intPtr);
         System.out.println("3 + 4 = " + result);
         

        -If you replace %pointer_functions(int,intp) by %pointer_class(int,intp), the interface is more class-like. +If you replace %pointer_functions(int, intp) by %pointer_class(int, intp), the interface is more class-like.

         intp intPtr = new intp();
        -example.add(3,4,intPtr.cast());
        +example.add(3, 4, intPtr.cast());
         int result = intPtr.value();
         System.out.println("3 + 4 = " + result);
         
        @@ -4798,7 +5263,7 @@ System.out.println("3 + 4 = " + result); See the SWIG Library chapter for further details.

        -

        25.8.3 Wrapping C arrays with Java arrays

        +

        26.8.3 Wrapping C arrays with Java arrays

        @@ -4811,9 +5276,9 @@ Let's consider an example: %include "arrays_java.i"; int array[4]; void populate(int x[]) { - int i; - for (i=0; i<4; i++) - x[i] = 100 + i; + int i; + for (i=0; i<4; i++) + x[i] = 100 + i; }

        @@ -4829,7 +5294,7 @@ example.populate(array); System.out.print("array: "); for (int i=0; i<array.length; i++) - System.out.print(array[i] + " "); + System.out.print(array[i] + " "); example.setArray(array); @@ -4837,7 +5302,7 @@ int[] global_array = example.getArray(); System.out.print("\nglobal_array: "); for (int i=0; i<array.length; i++) - System.out.print(global_array[i] + " "); + System.out.print(global_array[i] + " "); @@ -4865,7 +5330,7 @@ Please be aware that the typemaps in this library are not efficient as all the e There is an alternative approach using the SWIG array library and this is covered in the next section.

        -

        25.8.4 Unbounded C Arrays

        +

        26.8.4 Unbounded C Arrays

        @@ -4875,11 +5340,11 @@ Sometimes a C function expects an array to be passed as a pointer. For example,

         int sumitems(int *first, int nitems) {
        -    int i, sum = 0;
        -    for (i = 0; i < nitems; i++) {
        -        sum += first[i];
        -    }
        -    return sum;
        +  int i, sum = 0;
        +  for (i = 0; i < nitems; i++) {
        +    sum += first[i];
        +  }
        +  return sum;
         }
         
        @@ -4907,7 +5372,7 @@ int[] array = new int[10000000]; // Array of 10-million integers for (int i=0; i<array.length; i++) { // Set some values array[i] = i; } -int sum = example.sumitems(array,10000); +int sum = example.sumitems(array, 10000); System.out.println("Sum = " + sum); @@ -4939,7 +5404,7 @@ For example:

        -The %array_functions(type,name) macro generates four helper functions that can be used to create and +The %array_functions(type, name) macro generates four helper functions that can be used to create and destroy arrays and operate on elements. In this case, the functions are as follows:

        @@ -4960,15 +5425,15 @@ In Java, you would use the functions like this:
         SWIGTYPE_p_int array = example.new_intArray(10000000);  // Array of 10-million integers
         for (int i=0; i<10000; i++) {                           // Set some values
        -    example.intArray_setitem(array,i,i);
        +  example.intArray_setitem(array, i, i);
         }
        -int sum = example.sumitems(array,10000);
        +int sum = example.sumitems(array, 10000);
         System.out.println("Sum = " + sum);
         

        -If you replace %array_functions(int,intp) by %array_class(int,intp), the interface is more class-like +If you replace %array_functions(int, intp) by %array_class(int, intp), the interface is more class-like and a couple more helper functions are available for casting between the array and the type wrapper class.

        @@ -4989,9 +5454,9 @@ For instance, you will be able to do this in Java:
         intArray array = new intArray(10000000);  // Array of 10-million integers
         for (int i=0; i<10000; i++) {             // Set some values
        -    array.setitem(i,i);
        +  array.setitem(i, i);
         }
        -int sum = example.sumitems(array.cast(),10000);
        +int sum = example.sumitems(array.cast(), 10000);
         System.out.println("Sum = " + sum);
         
        @@ -5010,7 +5475,7 @@ well suited for applications in which you need to create buffers, package binary data, etc.

        -

        25.8.5 Binary data vs Strings

        +

        26.8.5 Binary data vs Strings

        @@ -5054,7 +5519,7 @@ len: 5 data: 68 69 0 6a 6b -

        25.8.6 Overriding new and delete to allocate from Java heap

        +

        26.8.6 Overriding new and delete to allocate from Java heap

        @@ -5128,7 +5593,7 @@ void * operator new(size_t t) { throw bad_alloc(); pJalloc->ref = 0; return static_cast<void *>( - static_cast<char *>(static_cast<void *>(pJalloc)) + sizeof(Jalloc)); + static_cast<char *>(static_cast<void *>(pJalloc)) + sizeof(Jalloc)); } } @@ -5171,7 +5636,7 @@ model and use these functions in place of malloc and free in your own code.

        -

        25.9 Java typemaps

        +

        26.9 Java typemaps

        @@ -5179,7 +5644,7 @@ This section describes how you can modify SWIG's default wrapping behavior for various C/C++ datatypes using the %typemap directive. You are advised to be familiar with the material in the "Typemaps" chapter. While not absolutely essential knowledge, this section assumes some familiarity with the Java Native Interface (JNI). -JNI documentation can be consulted either online at Sun's Java web site or from a good JNI book. +JNI documentation can be consulted either online at the Java web site or from a good JNI book. The following two books are recommended:

          @@ -5192,7 +5657,7 @@ Before proceeding, it should be stressed that typemaps are not a required part of using SWIG---the default wrapping behavior is enough in most cases. Typemaps are only used if you want to change some aspect of the generated code. -

          25.9.1 Default primitive type mappings

          +

          26.9.1 Default primitive type mappings

          @@ -5344,7 +5809,7 @@ However, the mappings allow the full range of values for each C type from Java.

          -

          25.9.2 Default typemaps for non-primitive types

          +

          26.9.2 Default typemaps for non-primitive types

          @@ -5359,7 +5824,7 @@ So in summary, the C/C++ pointer to non-primitive types is cast into the 64 bit The Java type is either the proxy class or type wrapper class.

          -

          25.9.3 Sixty four bit JVMs

          +

          26.9.3 Sixty four bit JVMs

          @@ -5372,7 +5837,7 @@ Unfortunately it won't of course hold true for JNI code.

          -

          25.9.4 What is a typemap?

          +

          26.9.4 What is a typemap?

          @@ -5491,11 +5956,11 @@ parameter is omitted):

          -int c = example.count('e',"Hello World");
          +int c = example.count('e', "Hello World");
           
          -

          25.9.5 Typemaps for mapping C/C++ types to Java types

          +

          26.9.5 Typemaps for mapping C/C++ types to Java types

          @@ -5543,6 +6008,17 @@ The most important of these implement the mapping of C/C++ types to Java types: In other words the typemap provides the conversion from the native method call return type. + +jboxtype +Java boxed type. + These are Java code typemaps to provide the Java boxed type, such as, Integer for C type int. + As autoboxing is only relevant to the Java primitive types, these are only provided for the + C types that map to Java primitive types. + This typemap is usually only used by C++ STL container wrappers that are wrapped by Java generic + types as the boxed type must be used instead of the unboxed/primitive type when declaring a Java generic type. + + + javadirectorin Conversion from jtype to jstype for director methods. @@ -5604,12 +6080,12 @@ The following code snippet might aid in understand aliasing rules better:

          -    short a;
          -    short* pa = 0;
          -    int i = 0x1234;
          +short a;
          +short* pa = 0;
          +int i = 0x1234;
           
          -    a = (short)i;    /* okay */
          -    a = *(short*)&i; /* breaks aliasing rules */
          +a = (short)i;    /* okay */
          +a = *(short*)&i; /* breaks aliasing rules */
           

          @@ -5618,15 +6094,15 @@ In SWIG, the "in" and "out" typemaps for pointers are typically

          -    %typemap(in) struct Foo * %{
          -      $1 = *(struct Foo **)&$input; /* cast jlong into C ptr */
          -    %}
          -    %typemap(out) struct Bar * %{
          -      *(struct Bar **)&$result = $1; /* cast C ptr into jlong */
          -    %} 
          -    struct Bar {...};
          -    struct Foo {...};
          -    struct Bar * FooBar(struct Foo *f);
          +%typemap(in) struct Foo * %{
          +  $1 = *(struct Foo **)&$input; /* cast jlong into C ptr */
          +%}
          +%typemap(out) struct Bar * %{
          +  *(struct Bar **)&$result = $1; /* cast C ptr into jlong */
          +%}
          +struct Bar {...};
          +struct Foo {...};
          +struct Bar * FooBar(struct Foo *f);
           

          @@ -5764,7 +6240,7 @@ These are listed below: -

          25.9.6 Java typemap attributes

          +

          26.9.6 Java typemap attributes

          @@ -5810,11 +6286,11 @@ The "javain" typemap has the optional 'pre', 'post' and 'pgcppname' attributes. Note that when the 'pre' or 'post' attributes are specified and the associated type is used in a constructor, a constructor helper function is generated. This is necessary as the Java proxy constructor wrapper makes a call to a support constructor using a this call. In Java the this call must be the first statement in the constructor body. The constructor body thus calls the helper function and the helper function instead makes the JNI call, ensuring the 'pre' code is called before the JNI call is made. There is a Date marshalling example showing 'pre', 'post' and 'pgcppname' attributes in action.

          -

          25.9.7 Java special variables

          +

          26.9.7 Java special variables

          -The standard SWIG special variables are available for use within typemaps as described in the Typemaps documentation, for example $1, $input,$result etc. +The standard SWIG special variables are available for use within typemaps as described in the Typemaps documentation, for example $1, $input, $result etc.

          @@ -5863,10 +6339,10 @@ If the typemap gets put into a function with void as return, $null will expand t

           SWIGEXPORT void JNICALL Java_jnifn(...) {
          -    if (error) {
          -      SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array element error");
          -      return ;
          -    }
          +  if (error) {
          +    SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array element error");
          +    return ;
          +  }
             ...
           }
           
          @@ -5877,10 +6353,10 @@ otherwise $null expands to NULL
           SWIGEXPORT jobject JNICALL Java_jnifn(...) {
          -    if (error) {
          -      SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array element error");
          -      return NULL;
          -    }
          +  if (error) {
          +    SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array element error");
          +    return NULL;
          +  }
             ...
           }
           
          @@ -5905,8 +6381,8 @@ Here is an example: } %inline %{ - class Class {...}; - Class * bar(Class cls, unsigned short ush) { return new Class(); }; + class Class {...}; + Class * bar(Class cls, unsigned short ush) { return new Class(); }; %} @@ -5992,7 +6468,7 @@ in that it is not fully qualified with the package name when using the nspace feature.

          -

          25.9.8 Typemaps for both C and C++ compilation

          +

          26.9.8 Typemaps for both C and C++ compilation

          @@ -6029,7 +6505,7 @@ If you do not intend your code to be targeting both C and C++ then your typemaps

          -

          25.9.9 Java code typemaps

          +

          26.9.9 Java code typemaps

          @@ -6070,9 +6546,12 @@ class modifiers for the Java class: default is "public class"

          %typemap(javacode)

          Java code is copied verbatim to the Java class: empty default +As there can only be one "javacode" typemap per class, also consider using the +%proxycode directive which can be used multiple times per class +and offers nearly identical functionality.
          -

          %typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized")

          +

          %typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized", parameters="")

          destructor wrapper - the delete() method (proxy classes only), used for all proxy classes except those which have a base class @@ -6081,9 +6560,12 @@ used for all proxy classes except those which have a base class
          Note that the delete() method name is configurable and is specified by the methodname attribute. The method modifiers are also configurable via the methodmodifiers attribute. +If a %javamethodmodifiers is attached to the class' destructor, +it will be used in preference to the methodmodifiers typemap attribute for the class. +The delete method's parameters declaration can be provided in the optional parameters typemap attribute.
          -

          %typemap(javadestruct_derived, methodname="delete", methodmodifiers="public synchronized")

          +

          %typemap(javadestruct_derived, methodname="delete", methodmodifiers="public synchronized", parameters="")

          destructor wrapper - the delete() method (proxy classes only), same as "javadestruct" but only used for derived proxy classes @@ -6092,6 +6574,9 @@ same as "javadestruct" but only used for derived proxy classes
          Note that the delete() method name is configurable and is specified by the methodname attribute. The method modifiers are also configurable via the methodmodifiers attribute. +If a %javamethodmodifiers is attached to the class' destructor, +it will be used in preference to the methodmodifiers typemap attribute for the class. +The delete method's parameters declaration can be provided in the optional parameters typemap attribute.

          %typemap(javaimports)

          @@ -6117,9 +6602,9 @@ Below shows an example modifying the finalizer, assuming the delete met
           %typemap(javafinalize) SWIGTYPE %{
          -   protected void finalize() {
          -     swig_delete();  // renamed to prevent conflict with existing delete method
          -   }
          +  protected void finalize() {
          +    swig_delete();  // renamed to prevent conflict with existing delete method
          +  }
           ]%
           
          @@ -6318,7 +6803,7 @@ to make the method and constructor public: -

          25.9.10 Director specific typemaps

          +

          26.9.10 Director specific typemaps

          @@ -6337,7 +6822,7 @@ For example, integers are converted as follows:

          -%typemap(directorin,descriptor="I") int "$input = (jint) $1;"
          +%typemap(directorin, descriptor="I") int "$input = (jint) $1;"
           
          @@ -6350,11 +6835,24 @@ A typemap for C character strings is:
          -%typemap(directorin,descriptor="Ljava/lang/String;") char *
          -  %{ $input = jenv->NewStringUTF($1); %}
          +%typemap(directorin, descriptor="Ljava/lang/String;", noblock=1) char * {
          +  $input = 0;
          +  if ($1) {
          +    $input = JCALL1(NewStringUTF, jenv, (const char *)$1);
          +    if (!$input) return $null;
          +  }
          +  Swig::LocalRefGuard $1_refguard(jenv, $input);
          +}
           
          +

          +The Swig::LocalRefGuard class should be used in directorin typemaps for newly allocated objects. +It is used to control local reference counts ensuring the count is decremented after the call up into Java has completed. +Its destructor simply calls jenv->DeleteLocalRef(obj) on the obj +passed in during construction. +

          +

          User-defined types have the default "descriptor" attribute "L$packagepath/$javaclassname;" where $packagepath @@ -6582,7 +7080,7 @@ The basic strategy here is to provide a default package typemap for the majority -

          25.10 Typemap Examples

          +

          26.10 Typemap Examples

          @@ -6592,7 +7090,7 @@ the SWIG library.

          -

          25.10.1 Simpler Java enums for enums without initializers

          +

          26.10.1 Simpler Java enums for enums without initializers

          @@ -6671,7 +7169,7 @@ This would be done by using the original versions of these typemaps in "enums.sw

          -

          25.10.2 Handling C++ exception specifications as Java exceptions

          +

          26.10.2 Handling C++ exception specifications as Java exceptions

          @@ -6796,7 +7294,7 @@ We could alternatively have used %rename to rename what() into

          -

          25.10.3 NaN Exception - exception handling for a particular type

          +

          26.10.3 NaN Exception - exception handling for a particular type

          @@ -6951,7 +7449,7 @@ If we were a martyr to the JNI cause, we could replace the succinct code within If we had, we would have put it in the "in" typemap which, like all JNI and Java typemaps, also supports the 'throws' attribute.

          -

          25.10.4 Converting Java String arrays to char **

          +

          26.10.4 Converting Java String arrays to char **

          @@ -6965,45 +7463,45 @@ The following SWIG interface file allows a Java String array to be used as a @@ -7095,7 +7593,7 @@ Lastly the "jni", "jtype" and "jstype" typemaps are also required to specify what Java types to use.

          -

          25.10.5 Expanding a Java object to multiple arguments

          +

          26.10.5 Expanding a Java object to multiple arguments

          @@ -7129,26 +7627,26 @@ previous example's typemaps:

           %typemap(in) (int argc, char **argv) {
          -    int i = 0;
          -    $1 = (*jenv)->GetArrayLength(jenv, $input);
          -    $2 = (char **) malloc(($1+1)*sizeof(char *));
          -    /* make a copy of each string */
          -    for (i = 0; i<$1; i++) {
          -        jstring j_string = (jstring)(*jenv)->GetObjectArrayElement(jenv, $input, i);
          -        const char * c_string = (*jenv)->GetStringUTFChars(jenv, j_string, 0);
          -        $2[i] = malloc((strlen(c_string)+1)*sizeof(char));
          -        strcpy($2[i], c_string);
          -        (*jenv)->ReleaseStringUTFChars(jenv, j_string, c_string);
          -        (*jenv)->DeleteLocalRef(jenv, j_string);
          -    }
          -    $2[i] = 0;
          +  int i = 0;
          +  $1 = (*jenv)->GetArrayLength(jenv, $input);
          +  $2 = (char **) malloc(($1+1)*sizeof(char *));
          +  /* make a copy of each string */
          +  for (i = 0; i<$1; i++) {
          +    jstring j_string = (jstring)(*jenv)->GetObjectArrayElement(jenv, $input, i);
          +    const char * c_string = (*jenv)->GetStringUTFChars(jenv, j_string, 0);
          +    $2[i] = malloc((strlen(c_string)+1)*sizeof(char));
          +    strcpy($2[i], c_string);
          +    (*jenv)->ReleaseStringUTFChars(jenv, j_string, c_string);
          +    (*jenv)->DeleteLocalRef(jenv, j_string);
          +  }
          +  $2[i] = 0;
           }
           
           %typemap(freearg) (int argc, char **argv) {
          -    int i;
          -    for (i=0; i<$1-1; i++)
          -      free($2[i]);
          -    free($2);
          +  int i;
          +  for (i=0; i<$1-1; i++)
          +    free($2[i]);
          +  free($2);
           }
           
           %typemap(jni) (int argc, char **argv) "jobjectArray"
          @@ -7177,7 +7675,7 @@ example.foo(new String[]{"red", "green", "blue", "white"});
           
          -

          25.10.6 Using typemaps to return arguments

          +

          26.10.6 Using typemaps to return arguments

          @@ -7211,7 +7709,7 @@ If we define a structure MyDouble containing a double member v /* Define a new structure to use instead of double * */ %inline %{ typedef struct { - double value; + double value; } MyDouble; %} @@ -7232,12 +7730,12 @@ argument of MyDouble instead of double *. This will allow the calling function to read the double * value after returning from the function. */ %typemap(in) double *OUTVALUE { - jclass clazz = jenv->FindClass("MyDouble"); - jfieldID fid = jenv->GetFieldID(clazz, "swigCPtr", "J"); - jlong cPtr = jenv->GetLongField($input, fid); - MyDouble *pMyDouble = NULL; - *(MyDouble **)&pMyDouble = *(MyDouble **)&cPtr; - $1 = &pMyDouble->value; + jclass clazz = jenv->FindClass("MyDouble"); + jfieldID fid = jenv->GetFieldID(clazz, "swigCPtr", "J"); + jlong cPtr = jenv->GetLongField($input, fid); + MyDouble *pMyDouble = NULL; + *(MyDouble **)&pMyDouble = *(MyDouble **)&cPtr; + $1 = &pMyDouble->value; } %typemap(jtype) double *OUTVALUE "MyDouble" @@ -7295,7 +7793,7 @@ $ java runme 1 12.0 340.0 -

          25.10.7 Adding Java downcasts to polymorphic return types

          +

          26.10.7 Adding Java downcasts to polymorphic return types

          @@ -7310,25 +7808,25 @@ Let's examine this with the following code: using namespace std; class Vehicle { public: - virtual void start() = 0; + virtual void start() = 0; ... }; class Ambulance : public Vehicle { - string vol; + string vol; public: - Ambulance(string volume) : vol(volume) {} - virtual void start() { - cout << "Ambulance started" << endl; - } - void sound_siren() { - cout << vol << " siren sounded!" << endl; - } + Ambulance(string volume) : vol(volume) {} + virtual void start() { + cout << "Ambulance started" << endl; + } + void sound_siren() { + cout << vol << " siren sounded!" << endl; + } ... }; Vehicle *vehicle_factory() { - return new Ambulance("Very loud"); + return new Ambulance("Very loud"); } @@ -7368,18 +7866,18 @@ The first is not to use a Java cast but a call to C++ to make the cast. Add this

           %exception Ambulance::dynamic_cast(Vehicle *vehicle) {
          -    $action
          +  $action
               if (!result) {
          -        jclass excep = jenv->FindClass("java/lang/ClassCastException");
          -        if (excep) {
          -            jenv->ThrowNew(excep, "dynamic_cast exception");
          -        }
          +      jclass excep = jenv->FindClass("java/lang/ClassCastException");
          +      if (excep) {
          +        jenv->ThrowNew(excep, "dynamic_cast exception");
          +      }
               }
           }
           %extend Ambulance {
          -    static Ambulance *dynamic_cast(Vehicle *vehicle) {
          -        return dynamic_cast<Ambulance *>(vehicle);
          -    }
          +  static Ambulance *dynamic_cast(Vehicle *vehicle) {
          +    return dynamic_cast<Ambulance *>(vehicle);
          +  }
           };
           
          @@ -7400,8 +7898,8 @@ Add the following before the definition of vehicle_factory:
           %typemap(out) Vehicle * {
          -    Ambulance *downcast = dynamic_cast<Ambulance *>($1);
          -    *(Ambulance **)&$result = downcast;
          +  Ambulance *downcast = dynamic_cast<Ambulance *>($1);
          +  *(Ambulance **)&$result = downcast;
           }
           
           %typemap(javaout) Vehicle * {
          @@ -7418,20 +7916,20 @@ Consider expanding our example with a new Vehicle type and a more flexible facto
           
           class FireEngine : public Vehicle {
           public:
          -    FireEngine() {}
          -    virtual void start() {
          -        cout << "FireEngine started" << endl;
          -    }
          -    void roll_out_hose() {
          -        cout << "Hose rolled out" << endl;
          -    }
          - ...
          +  FireEngine() {}
          +  virtual void start() {
          +    cout << "FireEngine started" << endl;
          +  }
          +  void roll_out_hose() {
          +    cout << "Hose rolled out" << endl;
          +  }
          +  ...
           };
           Vehicle *vehicle_factory(int vehicle_number) {
          -    if (vehicle_number == 0)
          -        return new Ambulance("Very loud");
          -    else
          -        return new FireEngine();
          +  if (vehicle_number == 0)
          +    return new Ambulance("Very loud");
          +  else
          +    return new FireEngine();
           }
           
          @@ -7460,37 +7958,37 @@ Note that in this case, the Java class is constructed using JNI code rather than } %typemap(out) Vehicle *vehicle_factory { - Ambulance *ambulance = dynamic_cast<Ambulance *>($1); - FireEngine *fireengine = dynamic_cast<FireEngine *>($1); - if (ambulance) { - // call the Ambulance(long cPtr, boolean cMemoryOwn) constructor - jclass clazz = jenv->FindClass("Ambulance"); - if (clazz) { - jmethodID mid = jenv->GetMethodID(clazz, "<init>", "(JZ)V"); - if (mid) { - jlong cptr = 0; - *(Ambulance **)&cptr = ambulance; - $result = jenv->NewObject(clazz, mid, cptr, false); - } - } - } else if (fireengine) { - // call the FireEngine(long cPtr, boolean cMemoryOwn) constructor - jclass clazz = jenv->FindClass("FireEngine"); - if (clazz) { - jmethodID mid = jenv->GetMethodID(clazz, "<init>", "(JZ)V"); - if (mid) { - jlong cptr = 0; - *(FireEngine **)&cptr = fireengine; - $result = jenv->NewObject(clazz, mid, cptr, false); - } - } + Ambulance *ambulance = dynamic_cast<Ambulance *>($1); + FireEngine *fireengine = dynamic_cast<FireEngine *>($1); + if (ambulance) { + // call the Ambulance(long cPtr, boolean cMemoryOwn) constructor + jclass clazz = jenv->FindClass("Ambulance"); + if (clazz) { + jmethodID mid = jenv->GetMethodID(clazz, "<init>", "(JZ)V"); + if (mid) { + jlong cptr = 0; + *(Ambulance **)&cptr = ambulance; + $result = jenv->NewObject(clazz, mid, cptr, false); + } } - else { - cout << "Unexpected type " << endl; + } else if (fireengine) { + // call the FireEngine(long cPtr, boolean cMemoryOwn) constructor + jclass clazz = jenv->FindClass("FireEngine"); + if (clazz) { + jmethodID mid = jenv->GetMethodID(clazz, "<init>", "(JZ)V"); + if (mid) { + jlong cptr = 0; + *(FireEngine **)&cptr = fireengine; + $result = jenv->NewObject(clazz, mid, cptr, false); + } } + } + else { + cout << "Unexpected type " << endl; + } - if (!$result) - cout << "Failed to create new java object" << endl; + if (!$result) + cout << "Failed to create new java object" << endl; }
          @@ -7501,7 +7999,7 @@ SWIG usually generates code which constructs the proxy classes using Java code a Note that the JNI code above uses a number of string lookups to call a constructor, whereas this would not occur using byte compiled Java code.

          -

          25.10.8 Adding an equals method to the Java classes

          +

          26.10.8 Adding an equals method to the Java classes

          @@ -7523,7 +8021,7 @@ Pure Java code methods like these can be easily added: return equal; } public int hashCode() { - return (int)getPointer(); + return (int)getPointer(); } %} @@ -7545,7 +8043,7 @@ System.out.println("foo1? " + foo1.equals(foo2)); -

          25.10.9 Void pointers and a common Java base class

          +

          26.10.9 Void pointers and a common Java base class

          @@ -7604,7 +8102,7 @@ This example contains some useful functionality which you may want in your code.

        • It also has a function which effectively implements a cast from the type of the proxy/type wrapper class to a void pointer. This is necessary for passing a proxy class or a type wrapper class to a function that takes a void pointer.
        -

        25.10.10 Struct pointer to pointer

        +

        26.10.10 Struct pointer to pointer

        @@ -7656,11 +8154,11 @@ The following Java code shows how we intend the code to be used:

        -    Butler jeeves = new Butler();
        -    example.HireButler(jeeves);
        -    System.out.println("Greeting:     " + jeeves.getGreeting());
        -    System.out.println("Availability: " + jeeves.getHoursAvailable() + " hours per day");
        -    example.FireButler(jeeves);
        +Butler jeeves = new Butler();
        +example.HireButler(jeeves);
        +System.out.println("Greeting:     " + jeeves.getGreeting());
        +System.out.println("Availability: " + jeeves.getHoursAvailable() + " hours per day");
        +example.FireButler(jeeves);
         
        @@ -7771,8 +8269,8 @@ To implement this, we use the above interface file code but remove the javac return pButler; } ~Butler() { - FireButler($self); - } + FireButler($self); + } } @@ -7784,7 +8282,7 @@ The C functional interface has been completely morphed into an object-oriented i the Butler class would behave much like any pure Java class and feel more natural to Java users.

        -

        25.10.11 Memory management when returning references to member variables

        +

        26.10.11 Memory management when returning references to member variables

        @@ -7799,7 +8297,7 @@ Consider the following C++ code:

         struct Wheel {
           int size;
        -  Wheel(int sz) : size(sz) {}
        +  Wheel(int sz = 0) : size(sz) {}
         };
         
         class Bike {
        @@ -7818,12 +8316,12 @@ and the following usage from Java after running the code through SWIG:
         
         
        -    Wheel wheel = new Bike(10).getWheel();
        -    System.out.println("wheel size: " + wheel.getSize());
        -    // Simulate a garbage collection
        -    System.gc();
        -    System.runFinalization();
        -    System.out.println("wheel size: " + wheel.getSize());
        +Wheel wheel = new Bike(10).getWheel();
        +System.out.println("wheel size: " + wheel.getSize());
        +// Simulate a garbage collection
        +System.gc();
        +System.runFinalization();
        +System.out.println("wheel size: " + wheel.getSize());
         
        @@ -7861,13 +8359,13 @@ is called using the following typemaps. // of dangling C++ pointer. Intended for methods that return pointers or // references to a member variable. %typemap(javaout) Wheel& getWheel { - long cPtr = $jnicall; - $javaclassname ret = null; - if (cPtr != 0) { - ret = new $javaclassname(cPtr, $owner); - ret.addReference(this); - } - return ret; + long cPtr = $jnicall; + $javaclassname ret = null; + if (cPtr != 0) { + ret = new $javaclassname(cPtr, $owner); + ret.addReference(this); + } + return ret; }
        @@ -7907,7 +8405,7 @@ public class Bike { Note the addReference call.

        -

        25.10.12 Memory management for objects passed to the C++ layer

        +

        26.10.12 Memory management for objects passed to the C++ layer

        @@ -7938,10 +8436,10 @@ and usage from C++

        -    Container container;
        -    Element element(20);
        -    container.setElement(&element);
        -    cout << "element.value: " << container.getElement()->value << endl;
        +Container container;
        +Element element(20);
        +container.setElement(&element);
        +cout << "element.value: " << container.getElement()->value << endl;
         
        @@ -7951,25 +8449,25 @@ and more or less equivalent usage from Java
        -    Container container = new Container();
        -    container.setElement(new Element(20));
        -    System.out.println("element value: " + container.getElement().getValue());
        +Container container = new Container();
        +container.setElement(new Element(20));
        +System.out.println("element value: " + container.getElement().getValue());
         

        The C++ code will always print out 20, but the value printed out may not be this in the Java equivalent code. -In order to understand why, consider a garbage collection occuring... +In order to understand why, consider a garbage collection occurring...

        -    Container container = new Container();
        -    container.setElement(new Element(20));
        -    // Simulate a garbage collection
        -    System.gc();
        -    System.runFinalization();
        -    System.out.println("element value: " + container.getElement().getValue());
        +Container container = new Container();
        +container.setElement(new Element(20));
        +// Simulate a garbage collection
        +System.gc();
        +System.runFinalization();
        +System.out.println("element value: " + container.getElement().getValue());
         
        @@ -7988,42 +8486,54 @@ public class Container { // Ensure that the GC doesn't collect any Element set from Java // as the underlying C++ class stores a shallow copy private Element elementReference; - private long getCPtrAndAddReference(Element element) { - elementReference = element; - return Element.getCPtr(element); - } public void setElement(Element e) { - exampleJNI.Container_setElement(swigCPtr, this, getCPtrAndAddReference(e), e); + exampleJNI.Container_setElement(swigCPtr, this, Element.getCPtr(e), e); + elementReference = e; } }

        -The following typemaps will generate the desired code. -The 'javain' typemap matches the input parameter type for the setElement method. -The 'javacode' typemap simply adds in the specified code into the Java proxy class. +The following typemaps can be used to generate this code:

        -%typemap(javain) Element *e "getCPtrAndAddReference($javainput)"
        -
         %typemap(javacode) Container %{
           // Ensure that the GC doesn't collect any element set from Java
           // as the underlying C++ class stores a shallow copy
           private Element elementReference;
        -  private long getCPtrAndAddReference(Element element) {
        -    elementReference = element;
        -    return Element.getCPtr(element);
        -  }
         %}
        +
        +%typemap(javain, 
        +         post="      elementReference = $javainput;"
        +         ) Element *e "Element.getCPtr($javainput)"
         
        +

        +The 'javacode' typemap simply adds in the specified code into the Java proxy class. +The 'javain' typemap matches the input parameter type and name for the setElement method and +the 'post' typemap attribute allows adding code after the JNI call. +The 'post' code is generated into a finally block after the JNI call so the resulting code isn't quite +as mentioned earlier, setElement is actually: +

        -

        25.10.13 Date marshalling using the javain typemap and associated attributes

        +
        +
        +  public void setElement(Element e) {
        +    try {
        +      exampleJNI.Container_setElement(swigCPtr, this, Element.getCPtr(e), e);
        +    } finally {
        +      elementReference = e;
        +    }
        +  }
        +
        +
        + +

        26.10.13 Date marshalling using the javain typemap and associated attributes

        @@ -8089,13 +8599,13 @@ The CDate & and const CDate & Java code is generated f

        where '$javaclassname' is translated into the proxy class name, CDate and '$javainput' is translated into the name of the parameter, eg dateIn. -From Java, the intention is then to call into a modifed API with something like: +From Java, the intention is then to call into a modified API with something like:

         java.util.GregorianCalendar calendarIn = 
        -    new java.util.GregorianCalendar(2011, java.util.Calendar.APRIL, 13, 0, 0, 0);
        +  new java.util.GregorianCalendar(2011, java.util.Calendar.APRIL, 13, 0, 0, 0);
         java.util.GregorianCalendar calendarOut = new java.util.GregorianCalendar();
         
         // Note in calls below, calendarIn remains unchanged and calendarOut 
        @@ -8200,7 +8710,7 @@ A few things to note:
         
         
         
        -

        25.11 Living with Java Directors

        +

        26.11 Living with Java Directors

        @@ -8315,7 +8825,7 @@ public class FooDerived extends Foo { public static FooDerived downcastFooDerived(Foo foo_object) { try { - return (foo_object != null ? (FooDerived) Foo.downcastFoo(foo_object); + return foo_object != null ? (FooDerived) Foo.downcastFoo(foo_object); } catch (ClassCastException exc) { @@ -8366,10 +8876,8 @@ public abstract class UserVisibleFoo extends Foo { public static UserVisibleFoo downcastUserVisibleFoo(Foo foo_object) { try { - return (foo_object != null ? (FooDerived) Foo.downcastFoo(foo_object) : null); - } - - catch (ClassCastException exc) { + return foo_object != null ? (FooDerived) Foo.downcastFoo(foo_object) : null; + } catch (ClassCastException exc) { // Wasn't a FooDerived object, some other subclass of Foo return null; } @@ -8381,10 +8889,10 @@ public abstract class UserVisibleFoo extends Foo {

      • -

        25.12 Odds and ends

        +

        26.12 Odds and ends

        -

        25.12.1 JavaDoc comments

        +

        26.12.1 JavaDoc comments

        @@ -8440,7 +8948,7 @@ public class Barmy { -

        25.12.2 Functional interface without proxy classes

        +

        26.12.2 Functional interface without proxy classes

        @@ -8457,8 +8965,8 @@ Consider the example we looked at when examining proxy classes:

         class Foo {
         public:
        -     int x;
        -     int spam(int num, Foo* foo);
        +  int x;
        +  int spam(int num, Foo* foo);
         };
         
        @@ -8501,7 +9009,7 @@ All destructors have to be called manually for example the delete_Foo(foo) -

        25.12.3 Using your own JNI functions

        +

        26.12.3 Using your own JNI functions

        @@ -8551,7 +9059,7 @@ This directive is only really useful if you want to mix your own hand crafted JN

        -

        25.12.4 Performance concerns and hints

        +

        26.12.4 Performance concerns and hints

        @@ -8572,7 +9080,7 @@ However, you will have to be careful about memory management and make sure that This method normally calls the C++ destructor or free() for C code.

        -

        25.12.5 Debugging

        +

        26.12.5 Debugging

        @@ -8594,7 +9102,7 @@ The -verbose:jni and -verbose:gc are also useful options for monitoring code beh

        -

        25.13 Java Examples

        +

        26.13 Java Examples

        diff --git a/Doc/Manual/Javascript.html b/Doc/Manual/Javascript.html index 16f674892..417ee4585 100644 --- a/Doc/Manual/Javascript.html +++ b/Doc/Manual/Javascript.html @@ -1,13 +1,13 @@ - + -

        26 SWIG and Javascript

        +

        27 SWIG and Javascript

          @@ -52,21 +52,21 @@

          This chapter describes SWIG's support of Javascript. It does not cover SWIG basics, but only information that is specific to this module.

          -

          26.1 Overview

          +

          27.1 Overview

          Javascript is a prototype-based scripting language that is dynamic, weakly typed and has first-class functions. Its arguably the most popular language for web development. -Javascript has gone beyond being a browser-based scripting language and with node.js, it is also used as a backend development language.

          +Javascript has gone beyond being a browser-based scripting language and with node.js, it is also used as a backend development language.

          Native Javascript extensions can be used for applications that embed a web-browser view or that embed a Javascript engine (such as node.js). Extending a general purpose web-browser is not possible as this would be a severe security issue.

          -

          SWIG Javascript currently supports JavascriptCore, the Javascript engine used by Safari/Webkit, and v8, which is used by Chromium and node.js.

          -

          WebKit is a modern browser implementation available as open-source which can be embedded into an application. +

          SWIG Javascript currently supports JavascriptCore, the Javascript engine used by Safari/Webkit, and v8, which is used by Chromium and node.js.

          +

          WebKit is a modern browser implementation available as open-source which can be embedded into an application. With node-webkit there is a platform which uses Google's Chromium as Web-Browser widget and node.js for javascript extensions.

          -

          26.2 Preliminaries

          +

          27.2 Preliminaries

          -

          26.2.1 Running SWIG

          +

          27.2.1 Running SWIG

          Suppose that you defined a SWIG module such as the following:

          @@ -101,7 +101,7 @@ that era had a component > 99. For example:

           $ swig -c++ -javascript -v8 -DV8_VERSION=0x032530 example.i
        -

        If you're targetting V8 >= 4.3.0, you would just run swig like so:

        +

        If you're targeting V8 >= 4.3.0, you would just run swig like so:

         $ swig -c++ -javascript -v8 example.i
        @@ -121,7 +121,7 @@ void example_initialize(v8::Handle<v8::Object> exports) Note: be aware that v8 has a C++ API, and thus, the generated modules must be compiled as C++.

        -

        26.2.2 Running Tests and Examples

        +

        27.2.2 Running Tests and Examples

        The configuration for tests and examples currently supports Linux and Mac only and not MinGW (Windows) yet.

        @@ -153,7 +153,7 @@ $ make check-javascript-test-suite ENGINE=jsc $ make check-javascript-examples V8_VERSION=0x032530 ENGINE=v8
        -

        26.2.3 Known Issues

        +

        27.2.3 Known Issues

        At the moment, the Javascript generators pass all tests syntactically, i.e., the generated source code compiles. However, there are still remaining runtime issues.

        @@ -161,7 +161,7 @@ $ make check-javascript-examples V8_VERSION=0x032530 ENGINE=v8
        • Default optional arguments do not work for all targeted interpreters

        • Multiple output arguments do not work for JSC

        • -
        • C89 incompatibily: the JSC generator might still generate C89 violating code

        • +
        • C89 incompatibility: the JSC generator might still generate C89 violating code

        • long long is not supported

        • %native is not supported

        • Javascript callbacks are not supported

        • @@ -170,12 +170,12 @@ $ make check-javascript-examples V8_VERSION=0x032530 ENGINE=v8

          The primary development environment has been Linux (Ubuntu 12.04). Windows and Mac OS X have been tested sporadically. Therefore, the generators might have more issues on those platforms. Please report back any problem you observe to help us improving this module quickly.

          -

          26.3 Integration

          +

          27.3 Integration

          This chapter gives a short introduction how to use a native Javascript extension: as a node.js module, and as an extension for an embedded Webkit.

          -

          26.3.1 Creating node.js Extensions

          +

          27.3.1 Creating node.js Extensions

          To install node.js you can download an installer from their web-site for Mac OS X and Windows. For Linux you can either build the source yourself and run sudo checkinstall or keep to the (probably stone-age) packaged version. For Ubuntu there is a PPA available.

          @@ -221,7 +221,7 @@ require("./build/Release/example")

          A more detailed explanation is given in the Examples section.

          -

          26.3.1.1 Troubleshooting

          +

          27.3.1.1 Troubleshooting

            @@ -233,12 +233,12 @@ require("./build/Release/example") $ sudo apt-get remove gyp -

            26.3.2 Embedded Webkit

            +

            27.3.2 Embedded Webkit

            Webkit is pre-installed on Mac OS X and available as a library for GTK.

            -

            26.3.2.1 Mac OS X

            +

            27.3.2.1 Mac OS X

            There is general information about programming with WebKit on Apple Developer Documentation. Details about Cocoa programming are not covered here.

            @@ -286,10 +286,10 @@ extern bool example_initialize(JSGlobalContextRef context, JSObjectRef* exports) @end -

            26.3.2.2 GTK

            +

            27.3.2.2 GTK

            -

            There is general information about programming GTK at GTK documentation and in the GTK tutorial, and for Webkit there is a Webkit GTK+ API Reference.

            +

            There is general information about programming GTK at GTK documentation and in the GTK tutorial, and for Webkit there is a Webkit GTK+ API Reference.

            An integration of a native extension 'example' would look like this:

            @@ -300,38 +300,38 @@ extern bool example_initialize(JSGlobalContextRef context);
             
             int main(int argc, char* argv[])
             {
            -    // Initialize GTK+
            -    gtk_init(&argc, &argv);
            +  // Initialize GTK+
            +  gtk_init(&argc, &argv);
             
            -    ...
            +  ...
             
            -    // Create a browser instance
            -    WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
            -    WebFrame *webframe = webkit_web_view_get_main_frame(webView);
            -    JSGlobalContextRef context = webkit_web_frame_get_global_context(webFrame);
            -    JSObjectRef global = JSContextGetGlobalObject(context);
            +  // Create a browser instance
            +  WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
            +  WebFrame *webframe = webkit_web_view_get_main_frame(webView);
            +  JSGlobalContextRef context = webkit_web_frame_get_global_context(webFrame);
            +  JSObjectRef global = JSContextGetGlobalObject(context);
             
            -    JSObjectRef exampleModule;
            -    example_initialize(context, &exampleModule);
            -    JSStringRef jsName = JSStringCreateWithUTF8CString("example");
            -    JSObjectSetProperty(context, global, jsName, exampleModule, kJSPropertyAttributeReadOnly, NULL);
            -    JSStringRelease(jsName);
            +  JSObjectRef exampleModule;
            +  example_initialize(context, &exampleModule);
            +  JSStringRef jsName = JSStringCreateWithUTF8CString("example");
            +  JSObjectSetProperty(context, global, jsName, exampleModule, kJSPropertyAttributeReadOnly, NULL);
            +  JSStringRelease(jsName);
             
            -    ...
            +  ...
             
            -    // Load a web page into the browser instance
            -    webkit_web_view_load_uri(webView, "http://www.webkitgtk.org/");
            +  // Load a web page into the browser instance
            +  webkit_web_view_load_uri(webView, "http://www.webkitgtk.org/");
             
            -    ...
            +  ...
             
            -    // Run the main GTK+ event loop
            -    gtk_main();
            +  // Run the main GTK+ event loop
            +  gtk_main();
             
            -    return 0;
            +  return 0;
             }
            -

            26.3.3 Creating Applications with node-webkit

            +

            27.3.3 Creating Applications with node-webkit

            To get started with node-webkit there is a very informative set of wiki pages.

            @@ -415,19 +415,19 @@ open new windows, and many more things. var example = require("example"); var x = 18; var y = 24; - var z = example.gcd(x,y); + var z = example.gcd(x, y); document.querySelector('#x').innerHTML = x; document.querySelector('#y').innerHTML = y; document.querySelector('#z').innerHTML = z; }; -

            26.4 Examples

            +

            27.4 Examples

            Some basic examples are shown here in more detail.

            -

            26.4.1 Simple

            +

            27.4.1 Simple

            The common example simple looks like this:

            @@ -467,7 +467,7 @@ var example = require("./build/Release/example"); // calling the global method var x = 42; var y = 105; -var g = example.gcd(x,y); +var g = example.gcd(x, y); // Accessing the global variable var f = example.Foo; @@ -477,7 +477,7 @@ example.Foo = 3.1415926;

            Note: ECMAScript 5, the currently implemented Javascript standard, does not have modules. node.js and other implementations provide this mechanism defined by the CommonJS group. For browsers this is provided by Browserify, for instance.

            -

            26.4.2 Class

            +

            27.4.2 Class

            The common example class defines three classes, Shape, Circle, and Square:

            @@ -604,15 +604,15 @@ at ReadStream.EventEmitter.emit (events.js:98:17) at emitKey (readline.js:1095:12)

            -Note: In ECMAScript 5 there is no concept for classes. Instead each function can be used as a constructor function which is executed by the 'new' operator. Furthermore, during construction the key property prototype of the constructor function is used to attach a prototype instance to the created object. A prototype is essentially an object itself that is the first-class delegate of a class used whenever the access to a property of an object fails. The very same prototype instance is shared among all instances of one type. Prototypal inheritance is explained in more detail on in Inheritance and the prototype chain, for instance. +Note: In ECMAScript 5 there is no concept for classes. Instead each function can be used as a constructor function which is executed by the 'new' operator. Furthermore, during construction the key property prototype of the constructor function is used to attach a prototype instance to the created object. A prototype is essentially an object itself that is the first-class delegate of a class used whenever the access to a property of an object fails. The very same prototype instance is shared among all instances of one type. Prototypal inheritance is explained in more detail on in Inheritance and the prototype chain, for instance.

            -

            26.5 Implementation

            +

            27.5 Implementation

            The Javascript Module implementation has taken a very different approach compared to other language modules in order to support different Javascript interpreters.

            -

            26.5.1 Source Code

            +

            27.5.1 Source Code

            The Javascript module is implemented in Source/Modules/javascript.cxx. It dispatches the code generation to a JSEmitter instance, V8Emitter or JSCEmitter. Additionally there are some helpers: Template, for templated code generation, and JSEmitterState, which is used to manage state information during AST traversal. This rough map shall make it easier to find a way through this huge source file:

            @@ -713,7 +713,7 @@ Template::Template(const String *code_) { ... } ... -

            26.5.2 Code Templates

            +

            27.5.2 Code Templates

            All generated code is created on the basis of code templates. The templates for JavascriptCore can be found in Lib/javascript/jsc/javascriptcode.swg, for v8 in Lib/javascript/v8/javascriptcode.swg.

            @@ -742,7 +742,7 @@ t_register.replace("$jsparent", state.clazz(NAME_MANGLED)) .trim(). print(f_init_static_wrappers); -

            A code template is registered with the JSEmitter via fragment(name, "template"), e.g.,

            +

            A code template is registered with the JSEmitter via fragment(name, "template"), e.g.,

             %fragment ("jsc_variable_declaration", "templates")
            @@ -752,7 +752,7 @@ t_register.replace("$jsparent", state.clazz(NAME_MANGLED))
             

            Template creates a copy of that string and Template::replace uses Swig's Replaceall to replace variables in the template. Template::trim can be used to eliminate leading and trailing whitespaces. Template::print is used to write the final template string to a Swig DOH (based on Printv). All methods allow chaining.

            -

            26.5.3 Emitter

            +

            27.5.3 Emitter

            The Javascript module delegates code generation to a JSEmitter instance. The following extract shows the essential interface:

            @@ -871,7 +871,7 @@ int JAVASCRIPT::classHandler(Node *n) {

            In enterClass the emitter stores state information that is necessary when processing class members. In exitClass the wrapper code for the whole class is generated.

            -

            26.5.4 Emitter states

            +

            27.5.4 Emitter states

            For storing information during the AST traversal the emitter provides a JSEmitterState with different slots to store data representing the scopes global, class, function, and variable.

            @@ -915,13 +915,13 @@ state.clazz(NAME, Getattr(n, "sym:name"));

            State information can be retrieved using state.clazz(NAME) or with Getattr on state.clazz() which actually returns a Hash instance.

            -

            26.5.5 Handling Exceptions in JavascriptCore

            +

            27.5.5 Handling Exceptions in JavascriptCore

            Applications with an embedded JavascriptCore should be able to present detailed exception messages that occur in the Javascript engine. Below is an example derived from code provided by Brian Barnes on how these exception details can be extracted.

            -void script_exception_to_string(JSContextRef js_context,JSValueRef exception_value_ref,char* return_error_string, int return_error_string_max_length)
            +void script_exception_to_string(JSContextRef js_context, JSValueRef exception_value_ref, char* return_error_string, int return_error_string_max_length)
             {
               JSObjectRef exception_object;
               JSValueRef value_ref;
            @@ -933,7 +933,7 @@ void script_exception_to_string(JSContextRef js_context,JSValueRef exception_val
               exception_object = JSValueToObject(js_context, exception_value_ref, NULL);
             
               /* source url */
            -  strcpy(return_error_string,"[");
            +  strcpy(return_error_string, "[");
               jsstring_property_name = JSStringCreateWithUTF8CString("sourceURL");
               value_ref = JSObjectGetProperty(js_context, exception_object, jsstring_property_name, &temporary_exception);
               JSStringRelease(jsstring_property_name);
            diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html
            index 954de54f7..560859234 100644
            --- a/Doc/Manual/Library.html
            +++ b/Doc/Manual/Library.html
            @@ -7,31 +7,38 @@
             
             
             
            -

            9 SWIG library

            +

            11 SWIG library

            • The %include directive and library search path -
            • C Arrays and Pointers +
            • C arrays and pointers -
            • C String Handling +
            • C string handling -
            • STL/C++ Library +
            • STL/C++ library
            • Utility Libraries @@ -60,7 +67,7 @@ Alternative libraries provide similar functionality. Please read this chapter carefully if you used the old libraries.

              -

              9.1 The %include directive and library search path

              +

              11.1 The %include directive and library search path

              @@ -92,7 +99,7 @@ Set the environment variable to hold an alternative library directory. The directories that are searched are displayed when using -verbose commandline option.

              -

              9.2 C Arrays and Pointers

              +

              11.2 C arrays and pointers

              @@ -104,7 +111,7 @@ pointers as class-like objects. Since these functions provide direct access to memory, their use is potentially unsafe and you should exercise caution.

              -

              9.2.1 cpointer.i

              +

              11.2.1 cpointer.i

              @@ -115,7 +122,7 @@ this module is in generating pointers to primitive datatypes such as

              -%pointer_functions(type,name) +%pointer_functions(type, name)

              @@ -195,7 +202,7 @@ Now, in Python:
               >>> import example
               >>> c = example.new_intp()     # Create an "int" for storing result
              ->>> example.add(3,4,c)         # Call function
              +>>> example.add(3, 4, c)       # Call function
               >>> example.intp_value(c)      # Dereference
               7
               >>> example.delete_intp(c)     # Delete
              @@ -205,7 +212,7 @@ Now, in Python:
               

              -%pointer_class(type,name) +%pointer_class(type, name)

              @@ -218,13 +225,13 @@ interface is as follows:
               struct name {
              -   name();                            // Create pointer object
              -  ~name();                            // Delete pointer object
              -   void assign(type value);           // Assign value
              -   type value();                      // Get value
              -   type *cast();                      // Cast the pointer to original type
              -   static name *frompointer(type *);  // Create class wrapper from existing
              -                                      // pointer
              +  name();                            // Create pointer object
              +  ~name();                           // Delete pointer object
              +  void assign(type value);           // Assign value
              +  type value();                      // Get value
              +  type *cast();                      // Cast the pointer to original type
              +  static name *frompointer(type *);  // Create class wrapper from existing
              +                                     // pointer
               };
               
              @@ -275,7 +282,7 @@ Now, in Python (using proxy classes)
               >>> import example
               >>> c = example.intp()         # Create an "int" for storing result
              ->>> example.add(3,4,c)         # Call function
              +>>> example.add(3, 4, c)       # Call function
               >>> c.value()                  # Dereference
               7
               
              @@ -320,7 +327,7 @@ In this example, the function int_to_uint() would be used to cast type Note: When working with simple pointers, typemaps can often be used to provide more seamless operation.

              -

              9.2.2 carrays.i

              +

              11.2.2 carrays.i

              @@ -331,7 +338,7 @@ raw C array data.

              -%array_functions(type,name) +%array_functions(type, name)

              @@ -384,10 +391,10 @@ function like this:
               void print_array(double x[10]) {
              -   int i;
              -   for (i = 0; i < 10; i++) {
              -      printf("[%d] = %g\n", i, x[i]);
              -   }
              +  int i;
              +  for (i = 0; i < 10; i++) {
              +    printf("[%d] = %g\n", i, x[i]);
              +  }
               }
               
              @@ -411,20 +418,20 @@ void print_array(double x[10]); Now, in a scripting language, you might write this:

              -
              +
              -a = new_doubleArray(10)           # Create an array
              -for i in range(0,10):
              -    doubleArray_setitem(a,i,2*i)  # Set a value
              -print_array(a)                    # Pass to C
              -delete_doubleArray(a)             # Destroy array
              +a = new_doubleArray(10)               # Create an array
              +for i in range(0, 10):
              +    doubleArray_setitem(a, i, 2 * i)  # Set a value
              +print_array(a)                        # Pass to C
              +delete_doubleArray(a)                 # Destroy array
               

              -%array_class(type,name) +%array_class(type, name)

              @@ -436,13 +443,13 @@ interface is as follows:
               struct name {
              -   name(int nelements);                  // Create an array
              -  ~name();                               // Delete array
              -   type getitem(int index);              // Return item
              -   void setitem(int index, type value);  // Set item
              -   type *cast();                         // Cast to original type
              -   static name *frompointer(type *);     // Create class wrapper from
              -                                         // existing pointer
              +  name(int nelements);                  // Create an array
              +  ~name();                              // Delete array
              +  type getitem(int index);              // Return item
              +  void setitem(int index, type value);  // Set item
              +  type *cast();                         // Cast to original type
              +  static name *frompointer(type *);     // Create class wrapper from
              +                                        // existing pointer
               };
               
              @@ -475,12 +482,12 @@ void print_array(double x[10]); Allows you to do this:

              -
              +
               import example
               c = example.doubleArray(10)  # Create double[10]
              -for i in range(0,10):
              -    c[i] = 2*i               # Assign values
              +for i in range(0, 10):
              +    c[i] = 2 * i             # Assign values
               example.print_array(c)       # Pass to C
               
              @@ -496,9 +503,10 @@ you should consider using a special array object rather than a bare pointer.

              Note: %array_functions() and %array_class() should not be used with types of char or char *. +SWIG's default handling of these types is to handle them as character strings and the two macros do not do enough to change this.

              -

              9.2.3 cmalloc.i

              +

              11.2.3 cmalloc.i

              @@ -507,7 +515,7 @@ This module defines macros for wrapping the low-level C memory allocation functi

              -%malloc(type [,name=type]) +%malloc(type [, name=type])

              @@ -530,7 +538,7 @@ is not a valid identifier (e.g., "int *", "double **", etc.).

              -%calloc(type [,name=type]) +%calloc(type [, name=type])

              @@ -551,7 +559,7 @@ If type is void, then the size parameter sz is requir

              -%realloc(type [,name=type]) +%realloc(type [, name=type])

              @@ -574,7 +582,7 @@ it holds 100 integers.

              -%free(type [,name=type]) +%free(type [, name=type])

              @@ -590,7 +598,7 @@ void free_name(type *ptr);

              -%sizeof(type [,name=type]) +%sizeof(type [, name=type])

              @@ -606,7 +614,7 @@ Creates the constant:

              -%allocators(type [,name=type]) +%allocators(type [, name=type])

              @@ -659,7 +667,7 @@ Now, in a script:

            -

            9.2.4 cdata.i

            +

            11.2.4 cdata.i

            @@ -716,14 +724,14 @@ Python example:

             >>> a = intArray(10)
            ->>> for i in range(0,10):
            +>>> for i in range(0, 10):
             ...    a[i] = i
            ->>> b = cdata(a,40)
            +>>> b = cdata(a, 40)
             >>> b
             '\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04
             \x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\t'
             >>> c = intArray(10)
            ->>> memmove(c,b)
            +>>> memmove(c, b)
             >>> print c[4]
             4
             >>>
            @@ -735,7 +743,7 @@ Since the size of data is not always known, the following macro is also defined:
             

            -%cdata(type [,name=type]) +%cdata(type [, name=type])

            @@ -761,7 +769,7 @@ char *cdata_name(type* ptr, int nitems) Clearly they are unsafe.

            -

            9.3 C String Handling

            +

            11.3 C string handling

            @@ -781,7 +789,7 @@ morality. The modules in this section provide basic functionality for manipulating raw C strings.

            -

            9.3.1 Default string handling

            +

            11.3.1 Default string handling

            @@ -801,7 +809,7 @@ target language. In other words, if you were using a language like Tcl, and you wrote this,

            -
            +
             % foo Hello
             
            @@ -822,7 +830,7 @@ interpreter and lead to a crash). Furthermore, the default behavior does not work well with binary data. Instead, strings are assumed to be NULL-terminated.

            -

            9.3.2 Passing binary data

            +

            11.3.2 Passing binary data

            @@ -852,10 +860,10 @@ size_t parity(char *str, size_t len, size_t initial); Now, in the target language, you can use binary string data like this:

            -
            +
             >>> s = "H\x00\x15eg\x09\x20"
            ->>> parity(s,0)
            +>>> parity(s, 0)
             
            @@ -864,7 +872,7 @@ In the wrapper function, the passed string will be expanded to a pointer and len The (char *STRING, int LENGTH) multi-argument typemap is also available in addition to (char *STRING, size_t LENGTH).

            -

            9.3.3 Using %newobject to release memory

            +

            11.3.3 Using %newobject to release memory

            @@ -874,9 +882,9 @@ If you have a function that allocates memory like this,

             char *foo() {
            -   char *result = (char *) malloc(...);
            -   ...
            -   return result;
            +  char *result = (char *) malloc(...);
            +  ...
            +  return result;
             }
             
            @@ -905,7 +913,7 @@ however, you may need to provide your own "newfree" typemap for other types. See Object ownership and %newobject for more details.

            -

            9.3.4 cstring.i

            +

            11.3.4 cstring.i

            @@ -919,16 +927,16 @@ implementation:

             void get_path(char *s) {
            -    // Potential buffer overflow---uh, oh.
            -    sprintf(s,"%s/%s", base_directory, sub_directory);
            +  // Potential buffer overflow---uh, oh.
            +  sprintf(s, "%s/%s", base_directory, sub_directory);
             }
             ...
             // Somewhere else in the C program
             {
            -    char path[1024];
            -    ...
            -    get_path(path);
            -    ...
            +  char path[1024];
            +  ...
            +  get_path(path);
            +  ...
             }
             
            @@ -1236,8 +1244,8 @@ returned in a parameter of type char **. For example:
             void foo(char **s) {
            -    *s = (char *) malloc(64);
            -    sprintf(*s, "Hello world\n");
            +  *s = (char *) malloc(64);
            +  sprintf(*s, "Hello world\n");
             }
             
            @@ -1284,10 +1292,10 @@ returned in two parameters of type char ** and int *. For exa
             void foo(char **s, int *sz) {
            -    *s = (char *) malloc(64);
            -    *sz = 64;
            -    // Write some binary data
            -    ...
            +  *s = (char *) malloc(64);
            +  *sz = 64;
            +  // Write some binary data
            +  ...
             }
             
            @@ -1337,7 +1345,7 @@ You could wrap it with a function like this:
             void my_get_data(char **result, int *len) {
            -   *result = get_data(len);
            +  *result = get_data(len);
             }
             
            @@ -1357,7 +1365,7 @@ to accomplish this in SWIG. This library provides support for a few common tech
          • If used in C++, this library uses new and delete [] for memory -allocation. If using ANSI C, the library uses malloc() and free(). +allocation. If using C, the library uses malloc() and free().
          • Rather than manipulating char * directly, you might consider using a special string @@ -1365,7 +1373,7 @@ structure or class instead.
          -

          9.4 STL/C++ Library

          +

          11.4 STL/C++ library

          @@ -1385,16 +1393,24 @@ The following table shows which C++ classes are supported and the equivalent SWI SWIG Interface library file + std::array (C++11) array std_array.i std::auto_ptr memory std_auto_ptr.i + std::complex complex std_complex.i std::deque deque std_deque.i std::list list std_list.i std::map map std_map.i + std::multimap (C++11) multimap std_multimap.i + std::multiset (C++11) multiset std_multiset.i std::pair utility std_pair.i std::set set std_set.i std::string string std_string.i + std::unordered_map (C++11) unordered_map std_unordered_map.i + std::unordered_multimap (C++11) unordered_multimap std_unordered_multimap.i + std::unordered_multiset (C++11) unordered_multiset std_unordered_multiset.i + std::unordered_set (C++11) unordered_set std_unordered_set.i std::vector vector std_vector.i - std::array array (C++11) std_array.i - std::shared_ptr shared_ptr (C++11) std_shared_ptr.i + std::wstring wstring std_wstring.i + std::shared_ptr (C++11) shared_ptr std_shared_ptr.i @@ -1404,7 +1420,7 @@ Please look for the library files in the appropriate language library directory.

          -

          9.4.1 std::string

          +

          11.4.1 std::string

          @@ -1460,7 +1476,7 @@ In the target language:

           x = my_struct();
          -x.foo="Hello World";      # assign with string
          +x.foo = "Hello World";    # assign with string
           print x.foo;              # print as string
           
          @@ -1488,7 +1504,7 @@ void foo(string s, const String &t); // std_string typemaps still applie -

          9.4.2 std::vector

          +

          11.4.2 std::vector

          @@ -1503,8 +1519,8 @@ instantiate different versions of vector for the types that you want to %include "std_vector.i" namespace std { - %template(vectori) vector<int>; - %template(vectord) vector<double>; + %template(vectori) vector<int>; + %template(vectord) vector<double>; }; @@ -1554,19 +1570,19 @@ To illustrate the use of this library, consider the following functions: #include <numeric> double average(std::vector<int> v) { - return std::accumulate(v.begin(),v.end(),0.0)/v.size(); + return std::accumulate(v.begin(), v.end(), 0.0)/v.size(); } std::vector<double> half(const std::vector<double>& v) { - std::vector<double> w(v); - for (unsigned int i=0; i<w.size(); i++) - w[i] /= 2.0; - return w; + std::vector<double> w(v); + for (unsigned int i=0; i<w.size(); i++) + w[i] /= 2.0; + return w; } void halve_in_place(std::vector<double>& v) { - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides<double>(),2.0)); + for (std::vector<double>::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } @@ -1585,8 +1601,8 @@ To wrap with SWIG, you might write the following: %include "std_vector.i" // Instantiate templates used by example namespace std { - %template(IntVector) vector<int>; - %template(DoubleVector) vector<double>; + %template(IntVector) vector<int>; + %template(DoubleVector) vector<double>; } // Include the header file with above prototypes @@ -1602,20 +1618,20 @@ Now, to illustrate the behavior in the scripting interpreter, consider this Pyth

           >>> from example import *
           >>> iv = IntVector(4)         # Create an vector<int>
          ->>> for i in range(0,4):
          +>>> for i in range(0, 4):
           ...      iv[i] = i
           >>> average(iv)               # Call method
           1.5
          ->>> average([0,1,2,3])        # Call with list
          +>>> average([0, 1, 2, 3])        # Call with list
           1.5
          ->>> half([1,2,3])             # Half a list
          -(0.5,1.0,1.5)
          ->>> halve_in_place([1,2,3])   # Oops
          +>>> half([1, 2, 3])             # Half a list
          +(0.5, 1.0, 1.5)
          +>>> halve_in_place([1, 2, 3])   # Oops
           Traceback (most recent call last):
             File "<stdin>", line 1, in ?
           TypeError: Type error. Expected _p_std__vectorTdouble_t
           >>> dv = DoubleVector(4)
          ->>> for i in range(0,4):
          +>>> for i in range(0, 4):
           ...       dv[i] = i
           >>> halve_in_place(dv)       # Ok
           >>> for i in dv:
          @@ -1629,7 +1645,7 @@ TypeError: Type error. Expected _p_std__vectorTdouble_t
           Traceback (most recent call last):
             File "<stdin>", line 1, in ?
             File "example.py", line 81, in __setitem__
          -    def __setitem__(*args): return apply(examplec.DoubleVector___setitem__,args)
          +    def __setitem__(*args): return apply(examplec.DoubleVector___setitem__, args)
           IndexError: vector index out of range
           >>>
           
          @@ -1645,7 +1661,7 @@ make sure you include the appropriate using or typedef directives. For %include "std_vector.i" namespace std { - %template(IntVector) vector<int>; + %template(IntVector) vector<int>; } using namespace std; @@ -1667,7 +1683,7 @@ if you want to make their head explode. details and the public API exposed to the interpreter vary.

          -

          9.4.3 STL exceptions

          +

          11.4.3 STL exceptions

          @@ -1717,7 +1733,10 @@ The %exception directive can be used by placing the following code befo Any thrown STL exceptions will then be gracefully handled instead of causing a crash.

          -

          9.4.4 shared_ptr smart pointer

          +

          11.4.4 shared_ptr smart pointer

          + + +

          11.4.4.1 shared_ptr basics

          @@ -1813,8 +1832,11 @@ System.out.println(val1 + " " + val2); +

          11.4.4.2 shared_ptr and inheritance

          + +

          -This shared_ptr library works quite differently to SWIG's normal, but somewhat limited, +The shared_ptr library works quite differently to SWIG's normal, but somewhat limited, smart pointer handling. The shared_ptr library does not generate extra wrappers, just for smart pointer handling, in addition to the proxy class. The normal proxy class including inheritance relationships is generated as usual. @@ -1892,7 +1914,7 @@ Adding the missing %shared_ptr macros will fix this:

          -%include "boost_shared_ptr.i"
          +%include <boost_shared_ptr.i>
           %shared_ptr(GrandParent);
           %shared_ptr(Parent);
           %shared_ptr(Child);
          @@ -1901,14 +1923,79 @@ Adding the missing %shared_ptr macros will fix this:
           
          +

          11.4.4.3 shared_ptr and method overloading

          + +

          -Note: There is somewhat limited support for %shared_ptr and the director feature -and the degress of success varies among the different target languages. -Please help to improve this support by providing patches with improvements. +A C++ compiler can disambiguate a method overloaded by a shared_ptr and one using the raw underlying type. +For example, either one of these methods can be called in C++: +

          + +
          +
          +int age(std::shared_ptr<GrandParent> num);
          +int age(GrandParent& num);
          +
          +
          + +

          +When wrapped by SWIG, disambiguation is not possible using the overloaded names as there is just one equivalent type (GrandParent) in the target language. +SWIG will choose to wrap just the first method by default. +Ambiguity in overloading discusses ways to control which method(s) gets wrapped using %ignore or %rename. +For the interested reader, SWIG detects that they are equivalent types via the typecheck typemaps in the shared_ptr library. +

          + +

          11.4.4.4 shared_ptr and templates

          + + +

          +The %shared_ptr macro should be used for all the required instantiations +of the template before each of the %template instantiations. +For example, consider number.h containing the following illustrative template: +

          + +
          +
          +#include <memory>
          +
          +template<int N> struct Number {
          +  int num;
          +  Number() : num(N) {}
          +  static std::shared_ptr<Number<N>> make() { return std::make_shared<Number<N>>(); }
          +};
          +
          +
          + +

          +The SWIG code below shows the required ordering: +

          + +
          +
          +%include <std_shared_ptr.i>
          +
          +%shared_ptr(Number<10>);
          +%shared_ptr(Number<42>);
          +
          +%{
          +  #include "number.h"
          +%}
          +%include "number.h"
          +
          +%template(Number10) Number<10>;
          +%template(Number42) Number<42>;
          +
          +
          + +

          11.4.4.5 shared_ptr and directors

          + + +

          +The languages that support shared_ptr also have support for using shared_ptr with directors.

          -

          9.4.5 auto_ptr smart pointer

          +

          11.4.5 auto_ptr smart pointer

          @@ -1957,10 +2044,10 @@ int value = k.getValue(); -

          9.5 Utility Libraries

          +

          11.5 Utility Libraries

          -

          9.5.1 exception.i

          +

          11.5.1 exception.i

          @@ -2011,11 +2098,11 @@ For example:

           %include "exception.i"
           %exception std::vector::getitem {
          -    try {
          -        $action
          -    } catch (std::out_of_range& e) {
          -        SWIG_exception(SWIG_IndexError,const_cast<char*>(e.what()));
          -    }
          +  try {
          +    $action
          +  } catch (std::out_of_range& e) {
          +    SWIG_exception(SWIG_IndexError, const_cast<char*>(e.what()));
          +  }
           }
           
          diff --git a/Doc/Manual/Lisp.html b/Doc/Manual/Lisp.html index 0867ba926..6eb448a12 100644 --- a/Doc/Manual/Lisp.html +++ b/Doc/Manual/Lisp.html @@ -7,11 +7,10 @@ -

          27 SWIG and Common Lisp

          +

          29 SWIG and Common Lisp

          @@ -38,26 +34,17 @@ finance, and also common in computer science education. There are more than 9 different implementations of common lisp which are available, all have different foreign function - interfaces. SWIG currently supports only the Allegro Common - Lisp, Common Foreign Function Interface(CFFI), CLisp and UFFI - foreign function interfaces. -

          -

          27.1 Allegro Common Lisp

          - - -

          - Allegro Common Lisp support in SWIG has been updated to include - support for both C and C++. You can read about the interface - here + interfaces. SWIG currently supports the + Common Foreign Function Interface(CFFI).

          -

          27.2 Common Foreign Function Interface(CFFI)

          +

          29.2 Common Foreign Function Interface(CFFI)

          CFFI, the Common Foreign Function Interface, is a portable foreign - function interface for ANSI Common Lisp systems, similar in - spirit to UFFI. Unlike UFFI, CFFI requires only a small set of + function interface for ANSI Common Lisp systems. + CFFI requires only a small set of low-level functionality from the Lisp implementation, such as calling a foreign function by name, allocating foreign memory, and dereferencing pointers. @@ -78,18 +65,9 @@ swig -cffi -module module-name file-name files and the various things which you can do with them.

          -

          27.2.1 Additional Commandline Options

          +

          29.2.1 Additional Commandline Options

          -

          -The following table list the additional commandline options available for the CLISP module. They can also be seen by using: -

          - -
          -swig -cffi -help 
          -
          -
          - @@ -119,12 +97,15 @@ swig -cffi -help
          CFFI specific options
          -

          27.2.2 Generating CFFI bindings

          +

          29.2.2 Generating CFFI bindings

          +

          + As we mentioned earlier the ideal way to use SWIG is to use interface files. To illustrate the use of it, let's assume that we have a file named test.h with the following C code: +

           #define y 5
          @@ -134,29 +115,31 @@ typedef int days;
           
           struct bar {
             short p, q;
          -    char a, b;
          -    int *z[1000];
          -    struct bar * n;
          +  char a, b;
          +  int *z[1000];
          +  struct bar * n;
           };
             
           struct   bar * my_struct;
           
           struct foo {
          -    int a;
          -    struct foo * b[100];
          -  
          +  int a;
          +  struct foo * b[100];
           };
           
           int pointer_func(void (*ClosureFun)( void* _fun, void* _data, void* _evt ), int p);
           
          -int func123(div_t * p,int **q[100],int r[][1000][10]);
          +int func123(div_t * p, int **q[100], int r[][1000][10]);
           
           void lispsort_double (int n, double * array);
           
           enum color { RED, BLUE, GREEN};
           
          +

          Corresponding to this we will write a simple interface file: +

          +
           %module test
           
          @@ -164,18 +147,20 @@ Corresponding to this we will write a simple interface file:
           
           
          +

          The generated SWIG Code will be: +

           ;;;SWIG wrapper code starts here
           
           (cl:defmacro defanonenum (&body enums)
              "Converts anonymous enums to defconstants."
          -  `(cl:progn ,@(cl:loop for value in enums
          +  `(cl:progn , @(cl:loop for value in enums
                                   for index = 0 then (cl:1+ index)
                                   when (cl:listp value) do (cl:setf index (cl:second value)
                                                                     value (cl:first value))
          -                        collect `(cl:defconstant ,value ,index))))
          +                        collect `(cl:defconstant , value , index))))
           
           (cl:eval-when (:compile-toplevel :load-toplevel)
             (cl:unless (cl:fboundp 'swig-lispify)
          @@ -281,7 +266,7 @@ Let's edit the interface file such that the C type "div_t*" is changed
           
           %typemap(cin) div_t* ":my-pointer";
           
          -%feature("intern_function","1");
          +%feature("intern_function", "1");
           %feature("export");
           
           %feature("inline") lispsort_double;
          @@ -306,7 +291,7 @@ The typemap(cin) ensures that for all arguments which are input
           The feature intern_function ensures that all C names are
                 interned using the swig-lispify function. The "1" given
                 to the feature is optional. The use of feature like
          -      %feature("intern_function","1"); globally enables
          +      %feature("intern_function", "1"); globally enables
                 interning for everything. If you want to target a single
                 function, or declaration then use the targeted version of
                 feature, %feature("intern_function", "my-lispify")
          @@ -396,7 +381,7 @@ The feature intern_function ensures that all C names are
           
           
          -

          27.2.3 Generating CFFI bindings for C++ code

          +

          29.2.3 Generating CFFI bindings for C++ code

          This feature to SWIG (for CFFI) is very new and still far from @@ -431,49 +416,48 @@ Also, while parsing the C++ file and generating C wrapper code SWIG %include "target/header.h" +

          Various features which were available for C headers can also be used here. The target header which we are going to use here is: +

           namespace OpenDemo {
             class Test
          -    {
          +  {
               public:
          -        float x;
          -        // constructors
          -        Test (void) {x = 0;}
          -        Test (float X) {x = X;}
          +      float x;
          +      // constructors
          +      Test (void) {x = 0;}
          +      Test (float X) {x = X;}
           
          -        // vector addition
          -        Test operator+ (const Test& v) const {return Test (x+v.x);}
          +      // vector addition
          +      Test operator+ (const Test& v) const {return Test (x+v.x);}
           
                 // length squared
          -        float lengthSquared (void) const {return this->dot (*this);}
          +      float lengthSquared (void) const {return this->dot (*this);}
           
          -        static float distance (const Test& a, const Test& b){return(a-b).length();}
          +      static float distance (const Test& a, const Test& b){return(a-b).length();}
           
          -        inline Test parallelComponent (const Test& unitBasis) const {
          -          return unitBasis * projection;
          -        }
          +      inline Test parallelComponent (const Test& unitBasis) const {
          +        return unitBasis * projection;
          +      }
           
          -        Test setYtoZero (void) const {return Test (this->x);}
          +      Test setYtoZero (void) const {return Test (this->x);}
           
          -        static const Test zero;
          -    };
          +      static const Test zero;
          +  };
           
          +  inline Test operator* (float s, const Test& v) {return v*s;}
           
          -   inline Test operator* (float s, const Test& v) {return v*s;}
          +  inline std::ostream& operator<< (std::ostream& o, const Test& v)
          +  {
          +    return o << "(" << v.x << ")";
          +  }
           
          -
          -    inline std::ostream& operator<< (std::ostream& o, const Test& v)
          -    {
          -        return o << "(" << v.x << ")";
          -    }
          -
          -
          -    inline Test RandomUnitVectorOnXZPlane (void)
          -    {
          -        return RandomVectorInUnitRadiusSphere().setYtoZero().normalize();
          -    }
          +  inline Test RandomUnitVectorOnXZPlane (void)
          +  {
          +    return RandomVectorInUnitRadiusSphere().setYtoZero().normalize();
          +  }
           }
           

          The interface used is:

          @@ -482,8 +466,10 @@ namespace OpenDemo { %include "test.cpp" +

          SWIG generates 3 files, the first one is a C wrap which we don't show, the second is the plain CFFI wrapper which is as shown below: +

           (cffi:defcfun ("_wrap_Test_x_set" Test_x_set) :void
             (self :pointer)
          @@ -532,11 +518,13 @@ SWIG generates 3 files, the first one is a C wrap which we don't show,
           (cffi:defcfun ("_wrap_RandomUnitVectorOnXZPlane" RandomUnitVectorOnXZPlane) :pointer)
           
          +

          The output is pretty good but it fails in disambiguating overloaded functions such as the constructor, in this case. One way of resolving this problem is to make the interface use the rename directiv, but hopefully there are better solutions. In addition SWIG also generates, a CLOS file +

          @@ -572,7 +560,7 @@ If you have any questions, suggestions, patches, etc., related to CFFI
                 module feel free to contact us on the SWIG mailing list, and
                 also please add a "[CFFI]" tag in the subject line.
           
          -

          27.2.4 Inserting user code into generated files

          +

          29.2.4 Inserting user code into generated files

          @@ -612,195 +600,5 @@ Note that the block %{ ... %} is effectively a shortcut for

          -

          27.3 CLISP

          - - -

          -CLISP is a feature-loaded - implementation of common lisp which is portable across most of the - operating system environments and hardware. CLISP includes an - interpreter, a compiler, a debugger, CLOS, MOP, a foreign - language interface, i18n, regular expressions, a socket - interface, and more. An X11 interface is available through CLX, - Garnet and CLUE/CLIO. Command line editing is provided by - readline. CLISP runs Maxima, ACL2 and many other Common Lisp - packages. -

          -

          - To run the clisp module of SWIG requires very little effort, you - just need to execute: -

          -
          -swig -clisp -module module-name   file-name 
          -
          -
          - -

          - Because of the high level nature of the CLISP FFI, the bindings - generated by SWIG may not be absolutely correct, and you may need - to modify them. The good thing is that you don't need to complex - interface file for the CLISP module. The CLISP module tries to - produce code which is both human readable and easily modifyable. -

          -

          27.3.1 Additional Commandline Options

          - - -

          -The following table list the additional commandline options available for the CLISP module. They can also be seen by using: -

          - -
          -swig -clisp -help 
          -
          -
          - - - - - - - - - - - - - - - -
          CLISP specific options
          -extern-allIf this option is given then clisp definitions for all the functions
          -and global variables will be created otherwise only definitions for
          -externed functions and variables are created. -
          -generate-typedefIf this option is given then def-c-type will be used to generate
          -shortcuts according to the typedefs in the input. -
          - -

          27.3.2 Details on CLISP bindings

          - - -

          -As mentioned earlier the CLISP bindings generated by SWIG may need -some modifications. The clisp module creates a lisp file with -the same name as the module name. This -lisp file contains a 'defpackage' declaration, with the -package name same as the module name. This package uses the -'common-lisp' and 'ffi' packages. Also, package exports all -the functions, structures and variables for which an ffi -binding was generated.
          -After generating the defpackage statement, the clisp module also -sets the default language. - -

          -(defpackage :test
          -    (:use :common-lisp :ffi)
          -  (:export
          -   :make-bar
          -   :bar-x
          -   :bar-y
          -   :bar-a
          -   :bar-b
          -   :bar-z
          -   :bar-n
          -   :pointer_func
          -   :func123
          -   :make-cfunr
          -   :lispsort_double
          -   :test123))
          -
          -(in-package :test)
          -
          -(default-foreign-language :stdc)
          -
          -

          -The ffi wrappers for functions and variables are generated as shown - below. When functions have arguments of type "double * array", - SWIG doesn't knows whether it is an 'out' argument or it is - an array which will be passed, so SWIG plays it safe by - declaring it as an '(array (ffi:c-ptr DOUBLE-FLOAT))'. For - arguments of type "int **z[100]" where SWIG has more - information, i.e., it knows that 'z' is an array of pointers to - pointers of integers, SWIG defines it to be '(z (ffi:c-ptr - (ffi:c-array (ffi:c-ptr (ffi:c-ptr ffi:int)) 100)))' -

          -
          -extern "C" {
          -int pointer_func(void (*ClosureFun)( void* _fun, void* _data, void* _evt ), int y);
          -
          -int func123(div_t * x,int **z[100],int y[][1000][10]);
          -
          -void lispsort_double (int n, double * array);
          -
          -void test123(float x , double y);
          -
          -}
          -
          -
          -(ffi:def-call-out pointer_func
          -    (:name "pointer_func")
          -  (:arguments (ClosureFun (ffi:c-function (:arguments (arg0 (ffi:c-pointer NIL))
          -                                                      (arg1 (ffi:c-pointer NIL))
          -                                                      (arg2 (ffi:c-pointer NIL)))
          -                                          (:return-type NIL)))
          -              (y ffi:int))
          -  (:return-type ffi:int)
          -  (:library +library-name+))
          -
          -(ffi:def-call-out func123
          -    (:name "func123")
          -  (:arguments (x (ffi:c-pointer div_t))
          -              (z (ffi:c-ptr (ffi:c-array (ffi:c-ptr (ffi:c-ptr ffi:int)) 100)))
          -              (y (ffi:c-ptr (ffi:c-ptr (ffi:c-array ffi:int (1000 10))))))
          -  (:return-type ffi:int)
          -  (:library +library-name+))
          -
          -
          -(ffi:def-call-out lispsort_double
          -    (:name "lispsort_double")
          -  (:arguments (n ffi:int)
          -              (array (ffi:c-ptr DOUBLE-FLOAT)))
          -  (:return-type NIL)
          -  (:library +library-name+))
          -
          -(ffi:def-call-out test123
          -    (:name "test")
          -  (:arguments (x SINGLE-FLOAT)
          -              (y DOUBLE-FLOAT))
          -  (:return-type NIL)
          -  (:library +library-name+))
          -
          -
          - -

          -The module also handles strutcures and #define constants as shown - below. SWIG automatically adds the constructors and accessors - created for the struct to the list of symbols exported by the - package. -

          -
          -struct bar {
          -    short x, y;
          -    char a, b;
          -    int *z[1000];
          -    struct bar * n;
          -};
          -
          -#define max 1000
          -
          -
          -(ffi:def-c-struct bar
          -    (x :type ffi:short)
          -  (y :type ffi:short)
          -  (a :type character)
          -  (b :type character)
          -  (z :type (ffi:c-array (ffi:c-ptr ffi:int) 1000))
          -  (n :type (ffi:c-pointer bar)))
          -
          -(defconstant max 1000)
          -
          -
          - -

          27.4 UFFI

          - - diff --git a/Doc/Manual/Lua.html b/Doc/Manual/Lua.html index 004ca6f2b..6633eaa38 100644 --- a/Doc/Manual/Lua.html +++ b/Doc/Manual/Lua.html @@ -77,7 +77,7 @@

          -Lua is an extension programming language designed to support general procedural programming with data description facilities. It also offers good support for object-oriented programming, functional programming, and data-driven programming. Lua is intended to be used as a powerful, light-weight configuration language for any program that needs one. Lua is implemented as a library, written in clean C (that is, in the common subset of ANSI C and C++). It's also a really tiny language, less than 6000 lines of code, which compiles to <100 kilobytes of binary code. It can be found at http://www.lua.org +Lua is an extension programming language designed to support general procedural programming with data description facilities. It also offers good support for object-oriented programming, functional programming, and data-driven programming. Lua is intended to be used as a powerful, light-weight configuration language for any program that needs one. Lua is implemented as a library, written in clean C (that is, in the common subset of ISO C and C++). It's also a really tiny language, less than 6000 lines of code, which compiles to <100 kilobytes of binary code. It can be found at http://www.lua.org

          eLua stands for Embedded Lua (can be thought of as a flavor of Lua) and offers the full implementation of the Lua programming language to the embedded world, extending it with specific features for efficient and portable software embedded development. eLua runs on smaller devices like microcontrollers and provides the full features of the regular Lua desktop version. More information on eLua can be found here: http://www.eluaproject.net @@ -193,27 +193,27 @@ Normally Lua is embedded into another program and will be statically linked. An extern int luaopen_example(lua_State* L); // declare the wrapped module -int main(int argc,char* argv[]) +int main(int argc, char* argv[]) { lua_State *L; if (argc<2) { - printf("%s: <filename.lua>\n",argv[0]); + printf("%s: <filename.lua>\n", argv[0]); return 0; } L=lua_open(); luaopen_base(L); // load basic libs (eg. print) luaopen_example(L); // load the wrapped module - if (luaL_loadfile(L,argv[1])==0) // load and run the file - lua_pcall(L,0,0,0); + if (luaL_loadfile(L, argv[1])==0) // load and run the file + lua_pcall(L, 0, 0, 0); else - printf("unable to load %s\n",argv[1]); + printf("unable to load %s\n", argv[1]); lua_close(L); return 0; }

          -A much improved set of code can be found in the Lua distribution src/lua/lua.c. Include your module, just add the external declaration & add a #define LUA_EXTRALIBS {"example",luaopen_example}, at the relevant place. +A much improved set of code can be found in the Lua distribution src/lua/lua.c. Include your module, just add the external declaration & add a #define LUA_EXTRALIBS {"example", luaopen_example}, at the relevant place.

          The exact commands for compiling and linking vary from platform to platform. Here is a possible set of commands of doing this: @@ -272,8 +272,8 @@ require("example") For those using Lua 5.0.x, you will also need an interpreter with the loadlib function (such as the default interpreter compiled with Lua). In order to dynamically load a module you must call the loadlib function with two parameters: the filename of the shared library, and the function exported by SWIG. Calling loadlib should return the function, which you then call to initialise the module

          -my_init=loadlib("example.so","luaopen_example") -- for Unix/Linux
          ---my_init=loadlib("example.dll","luaopen_example") -- for Windows
          +my_init=loadlib("example.so", "luaopen_example") -- for Unix/Linux
          +--my_init=loadlib("example.dll", "luaopen_example") -- for Windows
           assert(my_init) -- make sure it's not nil
           my_init()       -- call the init fn of the lib
           
          @@ -281,7 +281,7 @@ my_init() -- call the init fn of the lib Or can be done in a single line of Lua code

          -assert(loadlib("example.so","luaopen_example"))()
          +assert(loadlib("example.so", "luaopen_example"))()
           
          @@ -289,9 +289,9 @@ assert(loadlib("example.so","luaopen_example"))() If the code didn't work, don't panic. The best thing to do is to copy the module and your interpreter into a single directory and then execute the interpreter and try to manually load the module (take care, all this code is case sensitive).

          -a,b,c=package.loadlib("example.so","luaopen_example") -- for Unix/Linux
          ---a,b,c=package.loadlib("example.dll","luaopen_example") -- for Windows
          -print(a,b,c)
          +a, b, c=package.loadlib("example.so", "luaopen_example") -- for Unix/Linux
          +--a, b, c=package.loadlib("example.dll", "luaopen_example") -- for Windows
          +print(a, b, c)
           

          Note: for Lua 5.0:
          @@ -326,7 +326,7 @@ Assuming all goes well, you will be able to this:

           $ ./my_lua
          -> print(example.gcd(4,6))
          +> print(example.gcd(4, 6))
           2
           > print(example.Foo)
           3
          @@ -373,7 +373,7 @@ This can easily overwrite existing functions, so this must be used with care.
           This option is considered deprecated and will be removed in the near future.
           

          -> for k,v in pairs(example) do _G[k]=v end
          +> for k, v in pairs(example) do _G[k]=v end
           > print(fact(4))
           24
           >
          @@ -411,7 +411,7 @@ SWIG will effectively generate two functions example.Foo_set() and 
           > print(c)
           3
           > c=5 -- this will not effect the original example.Foo
          -> print(example.Foo,c)
          +> print(example.Foo, c)
           4    5
           

          @@ -486,7 +486,7 @@ Because Lua doesn't really have the concept of constants, C/C++ constants are no

          %module example
           %constant int ICONST=42;
           #define    SCONST      "Hello World"
          -enum Days{SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY};
          +enum Days{SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};
           

          This is 'effectively' converted into the following Lua code: @@ -521,9 +521,9 @@ Enums are exported into a class table. For example, given some enums:

          %module example
           enum Days { SUNDAY = 0, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY };
           struct Test {
          -    enum { TEST1 = 10, TEST2 = 20 };
          +  enum { TEST1 = 10, TEST2 = 20 };
           #ifdef __cplusplus // There are no static members in C
          -    static const int ICONST = 12;
          +  static const int ICONST = 12;
           #endif
           };
           
          @@ -584,8 +584,8 @@ int fclose(FILE *); When wrapped, you will be able to use the functions in a natural way from Lua. For example:

          -> f=example.fopen("junk","w")
          -> example.fputs("Hello World",f)
          +> f=example.fopen("junk", "w")
          +> example.fputs("Hello World", f)
           > example.fclose(f)
           

          @@ -601,7 +601,7 @@ FILE * -- it's a FILE* Lua enforces the integrity of its userdata, so it is virtually impossible to corrupt the data. But as the user of the pointer, you are responsible for freeing it, or closing any resources associated with it (just as you would in a C program). This does not apply so strictly to classes & structs (see below). One final note: if a function returns a NULL pointer, this is not encoded as a userdata, but as a Lua nil.

          -> f=example.fopen("not there","r") -- this will return a NULL in C
          +> f=example.fopen("not there", "r") -- this will return a NULL in C
           > print(f)
           nil
           
          @@ -613,7 +613,7 @@ nil If you wrap a C structure, it is also mapped to a Lua userdata. By adding a metatable to the userdata, this provides a very natural interface. For example,

          struct Point{
          -  int x,y;
          +  int x, y;
           };
           

          @@ -623,7 +623,7 @@ is used as follows: > p=example.new_Point() > p.x=3 > p.y=5 -> print(p.x,p.y) +> print(p.x, p.y) 3 5 >

          @@ -645,12 +645,12 @@ Like the pointer in the previous section, this is held as a userdata. However, a const members of a structure are read-only. Data members can also be forced to be read-only using the immutable directive. As with other immutables, setting attempts will be cause an error. For example:

          struct Foo {
          -   ...
          -   %immutable;
          -   int x;        // Read-only members
          -   char *name;
          -   %mutable;
          -   ...
          +  ...
          +  %immutable;
          +  int x;        // Read-only members
          +  char *name;
          +  %mutable;
          +  ...
           };
           

          @@ -661,11 +661,11 @@ When a member of a structure is itself a structure, it is handled as a pointer.

          struct Foo {
          -   int a;
          +  int a;
           };
           
           struct Bar {
          -   Foo f;
          +  Foo f;
           };
           

          @@ -695,8 +695,8 @@ Because the pointer points inside the structure, you can modify the contents and For eLua with the -eluac option, structure manipulation has to be performed with specific structure functions generated by SWIG. Let's say you have the following structure definition:

          struct data {
          -   int x, y;
          -   double z;
          +  int x, y;
          +  double z;
           };
           
           > --From eLua
          @@ -749,8 +749,8 @@ Class data members are accessed in the same manner as C structures. Static class
           

          class Spam {
           public:
          -   static void foo();
          -   static int bar;
          +  static void foo();
          +  static int bar;
           };
           

          @@ -871,9 +871,9 @@ Similarly, if you have a class like this,

          class Foo {
           public:
          -    Foo();
          -    Foo(const Foo &);
          -    ...
          +  Foo();
          +  Foo(const Foo &);
          +  ...
           };
           

          @@ -953,8 +953,8 @@ public: When wrapped, it works like you expect:

          -> c = Complex(3,4)
          -> d = Complex(7,8)
          +> c = Complex(3, 4)
          +> d = Complex(7, 8)
           > e = c + d
           > e:re()
           10.0
          @@ -984,7 +984,7 @@ There are ways to make this operator appear as part of the class using the %
           Also, be aware that certain operators don't map cleanly to Lua, and some Lua operators don't map cleanly to C++ operators. For instance, overloaded assignment operators don't map to Lua semantics and will be ignored, and C++ doesn't support Lua's concatenation operator (..).
           

          -In order to keep maximum compatibility within the different languages in SWIG, the Lua bindings uses the same set of operator names as python. Although internally it renames the functions to something else (on order to work with Lua). +In order to keep maximum compatibility within the different languages in SWIG, the Lua bindings uses the same set of operator names as Python. Although internally it renames the functions to something else (on order to work with Lua).

          The current list of operators which can be overloaded (and the alternative function names) are:

          • __add__ operator+ @@ -1000,42 +1000,40 @@ The current list of operators which can be overloaded (and the alternative funct
          • __le__ operator<=

          -Note: in Lua, only the equals, less than, and less than equals operators are defined. The other operators (!=,>,>=) are achieved by using a logical not applied to the results of other operators. +Note: in Lua, only the equals, less than, and less than equals operators are defined. The other operators (!=, >, >=) are achieved by using a logical not applied to the results of other operators.

          The following operators cannot be overloaded (mainly because they are not supported in Lua)

            -
          • ++ and --
          • +=,-=,*= etc
          • % operator (you have to use math.mod)
          • assignment operator
          • all bitwise/logical operations
          +
        • ++ and --
        • +=, -=, *= etc
        • % operator (you have to use math.mod)
        • assignment operator
        • all bitwise/logical operations

        SWIG also accepts the __str__() member function which converts an object to a string. This function should return a const char*, preferably to static memory. This will be used for the print() and tostring() functions in Lua. Assuming the complex class has a function

        -
        const char* __str__()
        -{
        -        static char buffer[255];
        -        sprintf(buffer,"Complex(%g,%g)",this->re(),this->im());
        -        return buffer;
        +
        const char* __str__() {
        +  static char buffer[255];
        +  sprintf(buffer, "Complex(%g, %g)", this->re(), this->im());
        +  return buffer;
         }
         

        Then this will support the following code in Lua

        -> c = Complex(3,4)
        -> d = Complex(7,8)
        +> c = Complex(3, 4)
        +> d = Complex(7, 8)
         > e = c + d
         > print(e)
        -Complex(10,12)
        +Complex(10, 12)
         > s=tostring(e) -- s is the number in string form
         > print(s)
        -Complex(10,12)
        +Complex(10, 12)
         

        It is also possible to overload the operator[], but currently this cannot be automatically performed. To overload the operator[] you need to provide two functions, __getitem__() and __setitem__()

        -
        class Complex
        -{
        -        //....
        -        double __getitem__(int i)const; // i is the index, returns the data
        -        void __setitem__(int i,double d); // i is the index, d is the data
        +
        class Complex {
        +  //....
        +  double __getitem__(int i)const; // i is the index, returns the data
        +  void __setitem__(int i, double d); // i is the index, d is the data
         };
         

        @@ -1090,27 +1088,28 @@ public: Now we extend it with some new code

        %extend Complex {
        -   const char *__str__() {
        -       static char tmp[1024];
        -       sprintf(tmp,"Complex(%g,%g)", $self->re(),$self->im());
        -       return tmp;
        -   }
        -   bool operator==(const Complex& c)
        -   {    return ($self->re()==c.re() && $self->im()==c.im());}
        +  const char *__str__() {
        +    static char tmp[1024];
        +    sprintf(tmp, "Complex(%g, %g)", $self->re(), $self->im());
        +    return tmp;
        +  }
        +  bool operator==(const Complex& c) {
        +    return ($self->re()==c.re() && $self->im()==c.im());
        +  }
         };
         

        Now, in Lua

        -> c = Complex(3,4)
        -> d = Complex(7,8)
        +> c = Complex(3, 4)
        +> d = Complex(7, 8)
         > e = c + d
         > print(e)      -- print uses __str__ to get the string form to print
        -Complex(10,12)
        -> print(e==Complex(10,12))      -- testing the == operator
        +Complex(10, 12)
        +> print(e==Complex(10, 12))  -- testing the == operator
         true
        -> print(e!=Complex(12,12))  -- the != uses the == operator
        +> print(e!=Complex(12, 12))  -- the != uses the == operator
         true
         

        @@ -1123,9 +1122,9 @@ Extend works with both C and C++ code, on classes and structs. It does not modif

        If you have a function that allocates memory like this,

        char *foo() {
        -   char *result = (char *) malloc(...);
        -   ...
        -   return result;
        +  char *result = (char *) malloc(...);
        +  ...
        +  return result;
         }
         
        @@ -1154,23 +1153,23 @@ char *foo(); template<class T1, class T2> struct pair { - typedef T1 first_type; - typedef T2 second_type; - T1 first; - T2 second; - pair(); - pair(const T1&, const T2&); + typedef T1 first_type; + typedef T2 second_type; + T1 first; + T2 second; + pair(); + pair(const T1&, const T2&); ~pair(); }; -%template(pairii) pair<int,int>; +%template(pairii) pair<int, int>;

        In Lua:

        -> p = example.pairii(3,4)
        -> print(p.first,p.second)
        +> p = example.pairii(3, 4)
        +> print(p.first, p.second)
         3    4
         

        @@ -1183,9 +1182,9 @@ Obviously, there is more to template wrapping than shown in this example. More d In certain C++ programs, it is common to use classes that have been wrapped by so-called "smart pointers." Generally, this involves the use of a template class that implements operator->() like this:

        template<class T> class SmartPtr {
        -   ...
        -   T *operator->();
        -   ...
        +  ...
        +  T *operator->();
        +  ...
         }
         

        @@ -1193,8 +1192,8 @@ Then, if you have a class like this,

        class Foo {
         public:
        -     int x;
        -     int bar();
        +  int x;
        +  int bar();
         };
         

        @@ -1264,11 +1263,11 @@ Using xpcall will allow you to obtain additional debug information (such as a st

         > function a() b() end -- function a() calls function b()
         > function b() message() end -- function b() calls C++ function message(), which throws 
        -> ok,res=pcall(a)  -- call the function
        -> print(ok,res)
        +> ok, res=pcall(a)  -- call the function
        +> print(ok, res)
         false   I died.
        -> ok,res=xpcall(a,debug.traceback)  -- call the function
        -> print(ok,res)
        +> ok, res=xpcall(a, debug.traceback)  -- call the function
        +> print(ok, res)
         false   I died.
         stack traceback:
                 [C]: in function 'message'
        @@ -1321,7 +1320,7 @@ If you have your own class which you want output as a string you will need to ad
         
         %typemap(throws) my_except
         %{ 
        -  lua_pushstring(L,$1.what()); // assuming my_except::what() returns a const char* message
        +  lua_pushstring(L, $1.what()); // assuming my_except::what() returns a const char* message
           SWIG_fail; // trigger the error handler
         %}
         
        @@ -1336,26 +1335,26 @@ class Exc { public: Exc(int c, const char *m) { code = c; - strncpy(msg,m,256); + strncpy(msg, m, 256); } int code; char msg[256]; }; void throw_exc() throw(Exc) { - throw(Exc(42,"Hosed")); + throw(Exc(42, "Hosed")); }

        Then the following code can be used (note: we use pcall to catch the error so we can process the exception).

        -> ok,res=pcall(throw_exc)
        +> ok, res=pcall(throw_exc)
         > print(ok)
         false
         > print(res)
         userdata: 0003D880
        -> print(res.code,res.msg)
        +> print(res.code, res.msg)
         42      Hosed
         >
         
        @@ -1536,8 +1535,8 @@ function
        %module example
         
         %typemap(in) int {
        -  $1 = (int) lua_tonumber(L,$input);
        -  printf("Received an integer : %d\n",$1);
        +  $1 = (int) lua_tonumber(L, $input);
        +  printf("Received an integer : %d\n", $1);
         }
         %inline %{
         extern int fact(int n);
        @@ -1564,17 +1563,17 @@ Received an integer : 6
         

        However for more complex functions which use input/output parameters or arrays, you will need to make use of <typemaps.i>, which contains typemaps for these situations. For example, consider these functions:

        void add(int x, int y, int *result) {
        -   *result = x + y;
        +  *result = x + y;
         }
         
         int sub(int *x1, int *y1) {
        -   return *x1-*y1;
        +  return *x1-*y1;
         }
         
         void swap(int *sx, int *sy) {
        -   int t=*sx;
        -   *sx=*sy;
        -   *sy=t;
        +  int t=*sx;
        +  *sx=*sy;
        +  *sy=t;
         }
         
        @@ -1595,13 +1594,13 @@ void swap(int *sx, int *sy);

        When wrapped, it gives the following results:

        > require "example"
        -> print(example.add(1,2))
        +> print(example.add(1, 2))
         3
        -> print(demo.sub(1,2))
        +> print(demo.sub(1, 2))
         -1
        -> a,b=1,2
        -> c,d=demo.swap(a,b)
        -> print(a,b,c,d)
        +> a, b=1, 2
        +> c, d=demo.swap(a, b)
        +> print(a, b, c, d)
         1       2       2       1
         
        @@ -1632,13 +1631,13 @@ More details can be found in the carrays.
        // using the C-array
         %include <carrays.i>
         // this declares a batch of function for manipulating C integer arrays
        -%array_functions(int,int)
        +%array_functions(int, int)
         
         extern void sort_int(int* arr, int len); // the function to wrap
         
         // using typemaps
         %include <typemaps.i>
        -%apply (double *INOUT,int) {(double* arr,int len)};
        +%apply (double *INOUT, int) {(double* arr, int len)};
         
         extern void sort_double(double* arr, int len); // the function to wrap
         
        @@ -1650,16 +1649,16 @@ ARRAY_SIZE=10 -- passing a C array to the sort_int() arr=example.new_int(ARRAY_SIZE) -- create the array -for i=0,ARRAY_SIZE-1 do -- index 0..9 (just like C) - example.int_setitem(arr,i,math.random(1000)) +for i=0, ARRAY_SIZE-1 do -- index 0..9 (just like C) + example.int_setitem(arr, i, math.random(1000)) end -example.sort_int(arr,ARRAY_SIZE) -- call the function +example.sort_int(arr, ARRAY_SIZE) -- call the function example.delete_int(arr) -- must delete the allocated memory -- use a typemap to call with a Lua-table -- one item of note: the typemap creates a copy, rather than edit-in-place t={} -- a Lua table -for i=1,ARRAY_SIZE do -- index 1..10 (Lua style) +for i=1, ARRAY_SIZE do -- index 1..10 (Lua style) t[i]=math.random(1000)/10 end t=example.sort_double(t) -- replace t with the result @@ -1703,7 +1702,7 @@ int Create_Math(iMath** pptr); // its creator (assume it mallocs)

        The usage is as follows:

        -
        ok,ptr=Create_Math() -- ptr is an iMath* which is returned with the int (ok)
        +
        ok, ptr=Create_Math() -- ptr is an iMath* which is returned with the int (ok)
         ptr=nil -- the iMath* will be GC'ed as normal
         
        @@ -1734,22 +1733,22 @@ ptr=nil -- the iMath* will be GC'ed as normal

        This section explains the SWIG specific Lua-C API. It does not cover the main Lua-C api, as this is well documented and not worth covering.

        -

        int SWIG_ConvertPtr(lua_State* L,int index,void** ptr,swig_type_info *type,int flags);

        +

        int SWIG_ConvertPtr(lua_State* L, int index, void** ptr, swig_type_info *type, int flags);

        This is the standard function used for converting a Lua userdata to a void*. It takes the value at the given index in the Lua state and converts it to a userdata. It will then provide the necessary type checks, confirming that the pointer is compatible with the type given in 'type'. Then finally setting '*ptr' to the pointer. If flags is set to SWIG_POINTER_DISOWN, this is will clear any ownership flag set on the object.
        -The returns a value which can be checked with the macro SWIG_IsOK() +This returns a value which can be checked with the macro SWIG_IsOK()
        -

        void SWIG_NewPointerObj(lua_State* L,void* ptr,swig_type_info *type,int own);

        +

        void SWIG_NewPointerObj(lua_State* L, void* ptr, swig_type_info *type, int own);

        This is the opposite of SWIG_ConvertPtr, as it pushes a new userdata which wrappers the pointer 'ptr' of type 'type'. The parameter 'own' specifies if the object is owned be Lua and if it is 1 then Lua will GC the object when the userdata is disposed of.
        -

        void* SWIG_MustGetPtr(lua_State* L,int index,swig_type_info *type,int flags,int argnum,const char* func_name);

        +

        void* SWIG_MustGetPtr(lua_State* L, int index, swig_type_info *type, int flags, int argnum, const char* func_name);

        This function is a version of SWIG_ConvertPtr(), except that it will either work, or it will trigger a lua_error() with a text error message. This function is rarely used, and may be deprecated in the future. @@ -1761,11 +1760,11 @@ This function is a version of SWIG_ConvertPtr(), except that it will either work This macro, when called within the context of a SWIG wrapped function, will jump to the error handler code. This will call any cleanup code (freeing any temp variables) and then triggers a lua_error.
        A common use for this code is:
         if (!SWIG_IsOK(SWIG_ConvertPtr( .....)){
        - lua_pushstring(L,"something bad happened");
        + lua_pushstring(L, "something bad happened");
          SWIG_fail;
         }
        -

        SWIG_fail_arg(char* func_name,int argnum,char* type)

        +

        SWIG_fail_arg(char* func_name, int argnum, char* type)

        This macro, when called within the context of a SWIG wrapped function, will display the error message and jump to the error handler code. The error message is of the form @@ -1773,7 +1772,7 @@ This macro, when called within the context of a SWIG wrapped function, will disp "Error in func_name (arg argnum), expected 'type' got 'whatever the type was'"
        -

        SWIG_fail_ptr(const char* fn_name,int argnum,swig_type_info* type);

        +

        SWIG_fail_ptr(const char* fn_name, int argnum, swig_type_info* type);

        Similar to SWIG_fail_arg, except that it will display the swig_type_info information instead.
        @@ -1877,24 +1876,24 @@ At initialisation time, it will then add to the interpreter a table called 'exam > print(example) table: 003F8F90 > m=getmetatable(example) -> table.foreach(m,print) +> table.foreach(m, print) .set table: 003F9088 .get table: 003F9038 __index function: 003F8FE0 __newindex function: 003F8FF8 > g=m['.get'] -> table.foreach(g,print) +> table.foreach(g, print) Foo function: 003FAFD8 >

        -The .get and .set tables are lookups connecting the variable name 'Foo' to the accessor/mutator functions (Foo_set,Foo_get) +The .get and .set tables are lookups connecting the variable name 'Foo' to the accessor/mutator functions (Foo_set, Foo_get)

        The Lua equivalent of the code for the __index and __newindex looks a bit like this

        -function __index(mod,name)
        +function __index(mod, name)
                 local g=getmetatable(mod)['.get'] -- gets the table
                 if not g then return nil end
                 local f=g[name] -- looks for the function
        @@ -1903,13 +1902,13 @@ function __index(mod,name)
                 return nil
         end
         
        -function __newindex(mod,name,value)
        +function __newindex(mod, name, value)
                 local s=getmetatable(mod)['.set'] -- gets the table
                 if not s then return end
                 local f=s[name] -- looks for the function
                 -- calls it to set the value
                 if type(f)=="function" then f(value)
        -        else rawset(mod,name,value) end
        +        else rawset(mod, name, value) end
         end
         

        @@ -1932,10 +1931,10 @@ Given a class class Point { public: - int x,y; + int x, y; Point(){x=y=0;} ~Point(){} - virtual void Print(){printf("Point @%p (%d,%d)\n",this,x,y);} + virtual void Print(){printf("Point @%p (%d, %d)\n", this, x, y);} };

        @@ -1949,7 +1948,7 @@ Some of the internals can be seen by looking at the metatable of a class: > print(p) userdata: 003FDB28 > m=getmetatable(p) -> table.foreach(m,print) +> table.foreach(m, print) .type Point __gc function: 003FB6C8 __newindex function: 003FB6B0 @@ -1965,7 +1964,7 @@ The '.type' attribute is the name of the class. The '.get' and '.set' tables wor The Lua equivalent of the code for enabling functions looks a little like this

        -function __index(obj,name)
        +function __index(obj, name)
                 local m=getmetatable(obj) -- gets the metatable
                 if not m then return nil end
                 local g=m['.get'] -- gets the attribute table
        diff --git a/Doc/Manual/Makefile b/Doc/Manual/Makefile
        index fb5f67c06..9505adb91 100644
        --- a/Doc/Manual/Makefile
        +++ b/Doc/Manual/Makefile
        @@ -1,10 +1,12 @@
         # Makefile for generating the SWIG documentation
         #
        -# Note that the htmldoc package needs to be installed, but requires patching (using the
        -# margin-left.patch file from this directory) in order to correctly generate the pdf docs.
        +# Note that the htmldoc package needs to be installed. wkhtmltopdf patched with qt is also required
        +# and can be installed from http://wkhtmltopdf.org/downloads.html.
        +#
         # The .html files are first processed and updated with chapter numbering and anchor names
         # are added to the HTML headings using the python scripts. The htmldoc program is then
        -# used to generate the PDF document and single page HTML version of the documentation.
        +# used to generate the single page HTML version of the documentation.
        +# wkhtmltopdf is used to generate the pdf document from the single page html file.
         # HTML TIDY (package also known as tidy) is also required and is used as an aid to HTML
         # validation.
         #
        @@ -87,3 +89,9 @@ linkchecker2:
         	cp *.png linkchecker-tmp
         	(cd linkchecker-tmp && linkchecker --config=../linkchecker.config -F text --no-warnings SWIGDocumentation.html)
         
        +# Simple check for relative links (there shouldn't be any), they don't translate properly creating the .pdf doc
        +# with wkhtmltopdf. For example, href="SWIG.html" needs to be href="SWIG.html#SWIG"
        +linkchecker3:
        +	@echo "The following list should just contain SWIGDocumentation.html and SWIGDocumentation.pdf,"
        +	@echo "as all links should have an anchor (with a #) or be a full url beginning http."
        +	grep 'href="' *.html | sed -e 's/.*href="\(.*\)">.*$$/\1/' | grep -v "#" | grep -v "^http" | grep -v "^style.css"
        diff --git a/Doc/Manual/Modula3.html b/Doc/Manual/Modula3.html
        index f324495a3..fc4ffa03c 100644
        --- a/Doc/Manual/Modula3.html
        +++ b/Doc/Manual/Modula3.html
        @@ -6,7 +6,7 @@
         
         
         
        -

        29 SWIG and Modula-3

        +

        31 SWIG and Modula-3

        -

        29.4.5 Exceptions

        +

        31.4.5 Exceptions

        @@ -817,7 +817,7 @@ you should declare %typemap("m3wrapinconv:throws") blah * %{OSError.E%}.

        -

        29.4.6 Example

        +

        31.4.6 Example

        @@ -858,16 +858,16 @@ where almost everything is generated by a typemap: RAISE E("invalid checksum"); END; FINALLY - M3toC.FreeSharedS(str,arg1); (* m3wrapfreearg *) + M3toC.FreeSharedS(str, arg1); (* m3wrapfreearg *) END; END Name; -

        29.5 More hints to the generator

        +

        31.5 More hints to the generator

        -

        29.5.1 Features

        +

        31.5.1 Features

        @@ -891,7 +891,7 @@ where almost everything is generated by a typemap: + %feature("constnumeric", "12") twelve;
        constnumeric %constnumeric(12) twelve; or - %feature("constnumeric","12") twelve; This feature can be used to tell Modula-3's back-end of SWIG the value of an identifier. This is necessary in the cases @@ -904,7 +904,7 @@ where almost everything is generated by a typemap:
        -

        29.5.2 Pragmas

        +

        31.5.2 Pragmas

        @@ -927,7 +927,7 @@ where almost everything is generated by a typemap:
        -

        29.6 Remarks

        +

        31.6 Remarks

        @@ -84,13 +88,13 @@ If you're not familiar with the Objective Caml language, you can visit The Ocaml Website.

        -

        31.1 Preliminaries

        +

        38.1 Preliminaries

        -SWIG 3.0 works with Ocaml 3.08.3 and above. Given the choice, +SWIG is compatible with OCaml 3.12.0 and above. Given the choice, you should use the latest stable release. The SWIG Ocaml module has -been tested on Linux (x86,PPC,Sparc) and Cygwin on Windows. The +been tested on Linux (x86, PPC, Sparc) and Cygwin on Windows. The best way to determine whether your system will work is to compile the examples and test-suite which come with SWIG. You can do this by running make check from the SWIG root directory after installing SWIG. @@ -102,7 +106,7 @@ file Examples/Makefile illustrate how to compile and link SWIG modules that will be loaded dynamically. This has only been tested on Linux so far.

        -

        31.1.1 Running SWIG

        +

        38.1.1 Running SWIG

        @@ -125,7 +129,7 @@ you will compile the file example_wrap.c with ocamlc or the resulting .ml and .mli files as well, and do the final link with -custom (not needed for native link).

        -

        31.1.2 Compiling the code

        +

        38.1.2 Compiling the code

        @@ -142,7 +146,7 @@ Use ocamlc or ocamlopt to compile your SWIG interface like:

        -% swig -ocaml -co swig.mli ; swig -ocaml co swig.ml
        +% swig -ocaml -co swig.mli ; swig -ocaml -co swig.ml
         % ocamlc -c swig.mli ; ocamlc -c swig.ml
         % ocamlc -c -ccopt "-I/usr/include/foo" example_wrap.c
         % ocamlc -c example.mli
        @@ -162,7 +166,7 @@ in C++ mode, you must:

        -

        31.1.3 The camlp4 module

        +

        38.1.3 The camlp4 module

        @@ -238,7 +242,7 @@ let b = C_string (getenv "PATH") -

        31.1.4 Using your module

        +

        38.1.4 Using your module

        @@ -252,7 +256,7 @@ option to build your functions into the primitive list. This option is not needed when you build native code.

        -

        31.1.5 Compilation problems and compiling with C++

        +

        38.1.5 Compilation problems and compiling with C++

        @@ -263,7 +267,7 @@ liberal with pointer types may not compile under the C++ compiler. Most code meant to be compiled as C++ will not have problems.

        -

        31.2 The low-level Ocaml/C interface

        +

        38.2 The low-level Ocaml/C interface

        @@ -327,7 +331,7 @@ A few functions exist which generate and return these: Because of this style, a typemap can return any kind of value it wants from a function. This enables out typemaps and inout typemaps to work well. The one thing to remember about outputting values -is that you must append them to the return list with swig_result = caml_list_append(swig_result,v). +is that you must append them to the return list with swig_result = caml_list_append(swig_result, v).

        @@ -336,7 +340,7 @@ appended. Upon return to caml space, the fnhelper function beautifies the result. A list containing a single item degrades to only that item (i.e. [ C_int 3 ] -> C_int 3), and a list containing more than one item is wrapped in C_list (i.e. [ C_char -'a' ; C_char 'b' -> C_list [ C_char 'a' ; C_char b +'a' ; C_char 'b' ] -> C_list [ C_char 'a' ; C_char 'b' ]). This is in order to make return values easier to handle when functions have only one return value, such as constructors, and operators. In addition, string, pointer, and object @@ -363,7 +367,7 @@ value items pass through directly, but you must make your own type signature for a function that uses value in this way.

        -

        31.2.1 The generated module

        +

        38.2.1 The generated module

        @@ -397,7 +401,7 @@ it describes the output SWIG will generate for class definitions. -

        31.2.2 Enums

        +

        38.2.2 Enums

        @@ -460,7 +464,7 @@ val x : Enum_test.c_obj = C_enum `a -

        31.2.2.1 Enum typing in Ocaml

        +

        38.2.2.1 Enum typing in Ocaml

        @@ -473,10 +477,10 @@ functions imported from different modules. You must convert values to master values using the swig_val function before sharing them with another module.

        -

        31.2.3 Arrays

        +

        38.2.3 Arrays

        -

        31.2.3.1 Simple types of bounded arrays

        +

        38.2.3.1 Simple types of bounded arrays

        @@ -497,7 +501,7 @@ arrays of simple types with known bounds in your code, but this only works for arrays whose bounds are completely specified.

        -

        31.2.3.2 Complex and unbounded arrays

        +

        38.2.3.2 Complex and unbounded arrays

        @@ -505,12 +509,12 @@ Unfortunately, unbounded arrays and pointers can't be handled in a completely general way by SWIG, because the end-condition of such an array can't be predicted. In some cases, it will be by consent (e.g. an array of four or more chars), sometimes by explicit length -(char *buffer, int len), and sometimes by sentinel value (0,-1,etc.). +(char *buffer, int len), and sometimes by sentinel value (0, -1, etc.). SWIG can't predict which of these methods will be used in the array, so you have to specify it for yourself in the form of a typemap.

        -

        31.2.3.3 Using an object

        +

        38.2.3.3 Using an object

        @@ -524,7 +528,7 @@ Consider writing an object when the ending condition of your array is complex, such as using a required sentinel, etc.

        -

        31.2.3.4 Example typemap for a function taking float * and int

        +

        38.2.3.4 Example typemap for a function taking float * and int

        @@ -560,7 +564,7 @@ void printfloats( float *tab, int len ) { $2 = caml_array_len($input); $1 = ($*1_type *)malloc( $2 * sizeof( float ) ); for( i = 0; i < $2; i++ ) { - $1[i] = caml_double_val(caml_array_nth($input,i)); + $1[i] = caml_double_val(caml_array_nth($input, i)); } } @@ -575,7 +579,7 @@ void printfloats( float *tab, int len ); -

        31.2.4 C++ Classes

        +

        38.2.4 C++ Classes

        @@ -618,7 +622,7 @@ the underlying pointer, so using create_[x]_from_ptr alters the returned value for the same object.

        -

        31.2.4.1 STL vector and string Example

        +

        38.2.4.1 STL vector and string Example

        @@ -660,7 +664,7 @@ module.

        -bash-2.05a$ ./example_top
        +bash-2.05a$ ./runme_top
                 Objective Caml version 3.06
         
                 Camlp4 Parsing version 3.06
        @@ -684,7 +688,7 @@ C_list
         - : Example.c_obj = C_void
         # x '[1] ;;
         - : Example.c_obj = C_string "bar"
        -# x -> set (1,"spam") ;;
        +# x -> set (1, "spam") ;;
         - : Example.c_obj = C_void
         # x '[1] ;;
         - : Example.c_obj = C_string "spam"
        @@ -698,7 +702,7 @@ baz
         #
         
        -

        31.2.4.2 C++ Class Example

        +

        38.2.4.2 C++ Class Example

        @@ -728,7 +732,7 @@ public: }; -

        31.2.4.3 Compiling the example

        +

        38.2.4.3 Compiling the example

        @@ -746,7 +750,7 @@ bash-2.05a$ ocamlmktop -custom swig.cmo -I `camlp4 -where` \
           -L$QTPATH/lib -cclib -lqt
         
        -

        31.2.4.4 Sample Session

        +

        38.2.4.4 Sample Session

        @@ -757,11 +761,11 @@ bash-2.05a$ ./qt_top
         
         # open Swig ;;
         # open Qt ;;
        -# let a = new_QApplication '(0,0) ;;
        +# let a = new_QApplication '(0, 0) ;;
         val a : Qt.c_obj = C_obj <fun>
        -# let hello = new_QPushButton '("hi",0) ;;
        +# let hello = new_QPushButton '("hi", 0) ;;
         val hello : Qt.c_obj = C_obj <fun>
        -# hello -> resize (100,30) ;;
        +# hello -> resize (100, 30) ;;
         - : Qt.c_obj = C_void
         # hello -> show () ;;
         - : Qt.c_obj = C_void
        @@ -773,10 +777,10 @@ Assuming you have a working installation of QT, you will see a window
         containing the string "hi" in a button.
         

        -

        31.2.5 Director Classes

        +

        38.2.5 Director Classes

        -

        31.2.5.1 Director Introduction

        +

        38.2.5.1 Director Introduction

        @@ -803,7 +807,7 @@ class foo { };

        -

        31.2.5.2 Overriding Methods in Ocaml

        +

        38.2.5.2 Overriding Methods in Ocaml

        @@ -831,11 +835,11 @@ In this example, I'll examine the objective caml code involved in providing an overloaded class. This example is contained in Examples/ocaml/shapes.

        -

        31.2.5.3 Director Usage Example

        +

        38.2.5.3 Director Usage Example

        -
        example_prog.ml
        +
        runme.ml
         open Swig
        @@ -854,13 +858,15 @@ let triangle_class pts ob meth args =
                    | _ -> raise (Failure "cover needs two double arguments."))
             | _ -> (invoke ob) meth args ;;
         
        +...
        +
         let triangle =
           new_derived_object
             new_shape
        -    (triangle_class ((0.0,0.0),(0.5,1.0),(1.0,0.0)))
        +    (triangle_class ((0.0, 0.0), (0.5, 1.0), (1.0, 0.6)))
             '() ;;
         
        -let _ = _draw_shape_coverage '(triangle, C_int 60, C_int 20) ;;
        +let _ = _draw_shape_coverage '(triangle, 60, 20) ;;
         
        @@ -890,7 +896,7 @@ in a more effortless style in ocaml, while leaving the "engine" part of the program in C++.

        -

        31.2.5.4 Creating director objects

        +

        38.2.5.4 Creating director objects

        @@ -901,7 +907,7 @@ The definition of the actual object triangle can be described this way: let triangle = new_derived_object new_shape - (triangle_class ((0.0,0.0),(0.5,1.0),(1.0,0.0))) + (triangle_class ((0.0, 0.0), (0.5, 1.0), (1.0, 0.0))) '() @@ -931,7 +937,7 @@ object from causing a core dump, as long as the object is destroyed properly.

        -

        31.2.5.5 Typemaps for directors, directorin, directorout, directorargout

        +

        38.2.5.5 Typemaps for directors, directorin, directorout, directorargout

        @@ -942,7 +948,7 @@ well as a function return value in the same way you provide function arguments, and to receive arguments the same way you normally receive function returns.

        -

        31.2.5.6 typemap

        +

        38.2.5.6 directorin typemap

        @@ -953,7 +959,7 @@ code receives when you are called. In general, a simple directorin typ can use the same body as a simple out typemap.

        -

        31.2.5.7 directorout typemap

        +

        38.2.5.7 directorout typemap

        @@ -964,7 +970,7 @@ for the same type, except when there are special requirements for object ownership, etc.

        -

        31.2.5.8 directorargout typemap

        +

        38.2.5.8 directorargout typemap

        @@ -981,14 +987,134 @@ In the event that you don't specify all of the necessary values, integral values will read zero, and struct or object returns have undefined results.

        -

        31.2.6 Exceptions

        +

        38.2.6 Exceptions

        -Catching exceptions is now supported using SWIG's %exception feature. A simple -but not too useful example is provided by the throw_exception testcase in -Examples/test-suite. You can provide your own exceptions, too. +If an error occurs in a C or C++ function, you may want to convert that error into an OCaml +exception. To do this, you can use the %exception directive. The %exception +directive simply lets you rewrite part of the generated wrapper code to include an error check. +It is detailed in full in the Exception handling with %exception section.

        +

        +In C, a function often indicates an error by returning a status code (e.g. a negative number +or a NULL pointer). Here is a simple example of how you might handle that: +

        + +
        +
        +%exception malloc {
        +  $action
        +  if (result == NULL) {
        +    caml_failwith("Not enough memory");
        +  }
        +}
        +void *malloc(size_t nbytes);
        +
        +
        + +

        +In OCaml: +

        + +
        +
        +# let a = _malloc (C_int 20000000000);;
        +Exception: Failure "Not enough memory".
        +#
        +
        +
        + +

        +If a library provides some kind of general error handling framework, you can also use +that. For example: +

        + +
        +
        +%exception {
        +  $action
        +  if (err_occurred()) {
        +    caml_failwith(err_message());
        +  }
        +}
        +
        +
        + +

        +If no declaration name is given to %exception, it is applied to all wrapper functions. +$action is a SWIG special variable and is replaced by the C/C++ function call being wrapped. +

        + +

        +C++ exceptions are also easy to handle. We can catch a C++ exception and rethrow it as +an OCaml exception like this: +

        + +
        +
        +%exception getitem {
        +  try {
        +    $action
        +  } catch (std::out_of_range &e) {
        +    caml_failwith(e.what());
        +  }
        +}
        +
        +class FooClass {
        +  public:
        +    int getitem(int index);      // Exception handling added
        +    ...
        +};
        +
        +
        + +

        +The language-independent exception.i library file can also be used +to raise exceptions. See the SWIG Library chapter. +

        + +

        38.3 Documentation Features

        + + +

        +The features described in this section can be used to generate documentation +comments (colloquially referred to as "docstrings") that can be read by +OCamldoc. +

        + +

        38.3.1 Module docstring

        + + +

        +The first documentation comment of an mli file is the comment +associated with the entire module. SWIG supports this by setting an +option of the %module directive. For example: +

        + +
        +
        +%module(docstring="This is the example module's docstring") example
        +
        +
        + +

        +When you have more than just a line or so, you can retain the +readability of the %module directive by using a macro. For +example: +

        + +
        +
        +%define DOCSTRING
        +"The `XmlResource` class allows program resources defining menus,
        +controls on a panel, etc. to be loaded from an XML file."
        +%enddef
        +
        +%module(docstring=DOCSTRING) xrc
        +
        +
        + diff --git a/Doc/Manual/Octave.html b/Doc/Manual/Octave.html index 9b9744f65..bd6b08ff9 100644 --- a/Doc/Manual/Octave.html +++ b/Doc/Manual/Octave.html @@ -9,7 +9,7 @@ -

        32 SWIG and Octave

        +

        29 SWIG and Octave

        -

        32.3.4 Constants and enums

        +

        29.3.4 Constants and enums

        @@ -297,7 +304,7 @@ ans = 3.1420

        %module swigexample
         %constant int ICONST=42;
         #define    SCONST      "Hello World"
        -enum Days{SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY};
        +enum Days{SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};
         

        @@ -309,12 +316,12 @@ swigexample.SCONST="Hello World" swigexample.SUNDAY=0 .... -

        32.3.5 Pointers

        +

        29.3.5 Pointers

        C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Given a wrapping of the <file.h> interface: - C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Given a wrapping of the <file.h> interface: + C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Given a wrapping of the <file.h> interface:

        %module swigexample
        @@ -329,8 +336,8 @@ When wrapped, you will be able to use the functions in a natural way from Octave
         
         
         octave:1> swigexample;
        -octave:2> f=swigexample.fopen("w","junk");
        -octave:3> swigexample.fputs("Hello world",f);
        +octave:2> f=swigexample.fopen("w", "junk");
        +octave:3> swigexample.fputs("Hello world", f);
         octave:4> swigexample.fclose(f);
         
        @@ -339,7 +346,7 @@ octave:4> swigexample.fclose(f);

        octave:1> swigexample;
        -octave:2> f=swigexample.fopen("junk","w");
        +octave:2> f=swigexample.fopen("junk", "w");
         octave:3> f
         f =
         
        @@ -352,11 +359,11 @@ f =
         

        octave:1> swigexample;
        -octave:2> f=swigexample.fopen("not there","r");
        +octave:2> f=swigexample.fopen("not there", "r");
         error: value on right hand side of assignment is undefined
         error: evaluating assignment expression near line 2, column 2 
        -

        32.3.6 Structures and C++ classes

        +

        29.3.6 Structures and C++ classes

        @@ -365,7 +372,7 @@ For each wrapped structure and class, a swig_ref will be exposed that h

        struct Point{
        -  int x,y;
        +  int x, y;
         };
         
        @@ -395,12 +402,12 @@ Methods also work as expected. For example, code wrapped in the following way
        class Point{
         public:
        -  int x,y;
        -  Point(int _x,int _y) : x(_x),y(_y) {}
        +  int x, y;
        +  Point(int _x, int _y) : x(_x), y(_y) {}
           double distance(const Point& rhs) {
        -    return sqrt(pow(x-rhs.x,2)+pow(y-rhs.y,2));
        +    return sqrt(pow(x-rhs.x, 2)+pow(y-rhs.y, 2));
           }
        -  void set(int _x,int _y) {
        +  void set(int _x, int _y) {
             x=_x; y=_y;
           }
         };
        @@ -410,8 +417,8 @@ can be used from Octave like this
         

        octave:1> swigexample;
        -octave:2> p1=swigexample.Point(3,5);
        -octave:3> p2=swigexample.Point(1,2);
        +octave:2> p1=swigexample.Point(3, 5);
        +octave:3> p2=swigexample.Point(1, 2);
         octave:4> p1.distance(p2)
         ans =  3.6056
         
        @@ -433,7 +440,7 @@ This differs from the usual pass-by-value (copy-on-write) semantics that Octave
        -octave:7> a=struct('x',4)
        +octave:7> a=struct('x', 4)
         a =
         {
           x =  4
        @@ -464,7 +471,7 @@ However, when dealing with wrapped objects, one gets the behavior
         
             
        -octave:2> a=Point(3,5)
        +octave:2> a=Point(3, 5)
         a =
         
         {
        @@ -478,7 +485,7 @@ b =
           Point, ptr = 0x9afbbb0
         }
         
        -octave:4> b.set(2,1);
        +octave:4> b.set(2, 1);
         octave:5> b.x, b.y
         ans =  2
         ans =  1
        @@ -491,7 +498,7 @@ ans =  1
         Depending on the ownership setting of a swig_ref, it may call C++ destructors when its reference count goes to zero. See the section on memory management below for details.
         

        -

        32.3.7 C++ inheritance

        +

        29.3.7 C++ inheritance

        @@ -500,7 +507,7 @@ This information contains the full class hierarchy. When an indexing operation ( the tree is walked to find a match in the current class as well as any of its bases. The lookup is then cached in the swig_ref.

        -

        32.3.8 C++ overloaded functions

        +

        29.3.8 C++ overloaded functions

        @@ -510,7 +517,7 @@ The dispatch function selects which overload to call (if any) based on the passe typecheck typemaps are used to analyze each argument, as well as assign precedence. See the chapter on typemaps for details.

        -

        32.3.9 C++ operators

        +

        29.3.9 C++ operators

        @@ -614,14 +621,14 @@ On the C++ side, the default mappings are as follows: Octave can also utilise friend (i.e. non-member) operators with a simple %rename: see the example in the Examples/octave/operator directory.

        -

        32.3.10 Class extension with %extend

        +

        29.3.10 Class extension with %extend

        The %extend directive works the same as in other modules.

        -You can use it to define special behavior, like for example defining Octave operators not mapped to C++ operators, or defining certain Octave mechanisms such as how an object prints. For example, the octave_value::{is_string,string_value,print} functions are routed to a special method __str__ that can be defined inside an %extend. +You can use it to define special behavior, like for example defining Octave operators not mapped to C++ operators, or defining certain Octave mechanisms such as how an object prints. For example, the octave_value::{is_string, string_value, print} functions are routed to a special method __str__ that can be defined inside an %extend.

         %extend A {
        @@ -639,7 +646,7 @@ Then in Octave one gets,
         octave:1> a=A(4);
         octave:2> a
         a = 4
        -octave:3> printf("%s\n",a);
        +octave:3> printf("%s\n", a);
         4
         octave:4> a.__str__()
         4
        @@ -653,7 +660,7 @@ Similarly, Octave can use the __float__ method to convert an object to
         Octave 3.8.0 and later versions will also map unary functions X() to the corresponding __X__ method, where X includes: abs(), acos(), acosh(), angle(), arg(), asin(), asinh(), atan(), atanh(), cbrt(), ceil(), conj(), cos(), cosh(), dawson(), erf(), erfc(), erfcinv(), erfcx(), erfi(), erfinv(), exp(), expm1(), finite(), fix(), floor(), gamma(), imag(), isalnum(), isalpha(), isascii(), iscntrl(), isdigit(), isgraph(), isinf(), islower(), isna(), isnan(), isprint(), ispunct(), isspace(), isupper(), isxdigit(), lgamma(), log(), log10(), log1p(), log2(), real(), round(), roundb(), signbit(), signum(), sin(), sinh(), sqrt(), tan(), tanh(), toascii(), tolower(), toupper()
         

        -

        32.3.11 C++ templates

        +

        29.3.11 C++ templates

        @@ -663,10 +670,10 @@ For example, function templates can be instantiated as follows:

        %module swigexample
         %inline {
        - template<class __scalar>
        -   __scalar mul(__scalar a,__scalar b) {
        -   return a*b;
        - }
        +  template<class __scalar>
        +    __scalar mul(__scalar a, __scalar b) {
        +    return a*b;
        +  }
         }
         %include <std_complex.i>
         %template(mul) mul<std::complex<double> >
        @@ -677,11 +684,11 @@ and then used from Octave
         

        -octave:1> mul(4,3)
        +octave:1> mul(4, 3)
         ans =  12
        -octave:2> mul(4.2,3.6)
        +octave:2> mul(4.2, 3.6)
         ans =  15.120
        -octave:3> mul(3+4i,10+2i)
        +octave:3> mul(3+4i, 10+2i)
         ans =  22 + 46i
         
        @@ -722,18 +729,18 @@ octave:2> a=sum_complex(2+3i); octave:3> a.add(2) ans = -(4,3) +(4, 3) octave:4> a.add(3+i) ans = -(7,4) +(7, 4)
        -

        32.3.12 C++ Smart Pointers

        +

        29.3.12 C++ Smart Pointers

        -

        32.3.12.1 The shared_ptr Smart Pointer

        +

        29.3.12.1 The shared_ptr Smart Pointer

        @@ -744,14 +751,14 @@ in the shared_ptr smart pointer -

        32.3.12.2 Generic Smart Pointers

        +

        29.3.12.2 Generic Smart Pointers

        C++ smart pointers are fully supported as in other modules.

        -

        32.3.13 Directors (calling Octave from C++ code)

        +

        29.3.13 Directors (calling Octave from C++ code)

        @@ -766,7 +773,7 @@ For example,

         octave:1> a=subclass();
         octave:2> a.my_var = 4;
        -octave:3> a.my_method = @(self) printf("my_var = ",self.my_var);
        +octave:3> a.my_method = @(self) printf("my_var = ", self.my_var);
         octave:4> a.my_method();
         my_var = 4
         
        @@ -790,7 +797,7 @@ void call_your_method(A& a) { Then from Octave you can say:

        -octave:1> B=@() subclass(A(),@my_method);
        +octave:1> B=@() subclass(A(), @my_method);
         octave:2> function my_method(self)
         octave:3>   printf("octave-side routine called\n");
         octave:4> end
        @@ -801,7 +808,7 @@ octave-side routine called
         or more concisely,
         

        -octave:1> B=@() subclass(A(),'my_method',@(self) printf("octave-side routine called\n"));
        +octave:1> B=@() subclass(A(), 'my_method', @(self) printf("octave-side routine called\n"));
         octave:2> call_your_method(B());
         octave-side routine called
         
        @@ -809,10 +816,10 @@ octave-side routine called Note that you have to enable directors via the %feature directive (see other modules for this).

        -subclass() will accept any number of C++ bases or other subclass()'ed objects, (string,octave_value) pairs, and function_handles. In the first case, these are taken as base classes; in the second case, as named members (either variables or functions, depending on whether the given value is a function handle); in the third case, as member functions whose name is taken from the given function handle. E.g., +subclass() will accept any number of C++ bases or other subclass()'ed objects, (string, octave_value) pairs, and function_handles. In the first case, these are taken as base classes; in the second case, as named members (either variables or functions, depending on whether the given value is a function handle); in the third case, as member functions whose name is taken from the given function handle. E.g.,

        -octave:1> B=@(some_var=2) subclass(A(),'some_var',some_var,@some_func,'another_func',
        +octave:1> B=@(some_var=2) subclass(A(), 'some_var', some_var, @some_func, 'another_func',
         @(self) do_stuff())
         

        @@ -822,7 +829,7 @@ You can also assign non-C++ member variables and functions after construct time. There is limited support for explicitly referencing C++ bases. So, in the example above, we could have

        -octave:1> B=@() subclass(A(),@my_method);
        +octave:1> B=@() subclass(A(), @my_method);
         octave:2> function my_method(self)
         octave:3>   self.A.my_method();
         octave:4>   printf("octave-side routine called\n");
        @@ -832,14 +839,14 @@ c-side routine called
         octave-side routine called
         
        -

        32.3.14 Threads

        +

        29.3.14 Threads

        The use of threads in wrapped Director code is not supported; i.e., an Octave-side implementation of a C++ class must be called from the Octave interpreter's thread. Anything fancier (apartment/queue model, whatever) is left to the user. Without anything fancier, this amounts to the limitation that Octave must drive the module... like, for example, an optimization package that calls Octave to evaluate an objective function.

        -

        32.3.15 Memory management

        +

        29.3.15 Memory management

        @@ -873,21 +880,21 @@ The %newobject directive may be used to control this behavior for pointers retur In the case where one wishes for the C++ side to own an object that was created in Octave (especially a Director object), one can use the __disown() method to invert this logic. Then letting the Octave reference count go to zero will not destroy the object, but destroying the object will invalidate the Octave-side object if it still exists (and call destructors of other C++ bases in the case of multiple inheritance/subclass()'ing).

        -

        32.3.16 STL support

        +

        29.3.16 STL support

        Various STL library files are provided for wrapping STL containers.

        -

        32.3.17 Matrix typemaps

        +

        29.3.17 Matrix typemaps

        Octave provides a rich set of classes for dealing with matrices. Currently there are no built-in typemaps to deal with those. However, these are relatively straight forward for users to add themselves (see the docs on typemaps). Without much work (a single typemap decl-- say, 5 lines of code in the interface file), it would be possible to have a function

        -double my_det(const double* mat,int m,int n);
        +double my_det(const double* mat, int m, int n);
         

        that is accessed from Octave as, diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 8d7b866d6..766ccaede 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -7,7 +7,7 @@ -

        33 SWIG and Perl5

        +

        30 SWIG and Perl5

          @@ -97,7 +97,7 @@ later. We're no longer testing regularly with older versions, but Perl 5.6 seems to mostly work, while older versions don't.

          -

          33.1 Overview

          +

          30.1 Overview

          @@ -118,11 +118,11 @@ described. Advanced customization features, typemaps, and other options are found near the end of the chapter.

          -

          33.2 Preliminaries

          +

          30.2 Preliminaries

          -To build a Perl5 module, run SWIG using the -perl option as +To build a Perl5 module, run SWIG using the -perl or -perl5 option as follows:

          @@ -143,7 +143,7 @@ To build the module, you will need to compile the file example_wrap.c and link it with the rest of your program.

          -

          33.2.1 Getting the right header files

          +

          30.2.1 Getting the right header files

          @@ -175,7 +175,7 @@ $ perl -e 'use Config; print "$Config{archlib}\n";'

        -

        33.2.2 Compiling a dynamic module

        +

        30.2.2 Compiling a dynamic module

        @@ -197,7 +197,7 @@ SWIG tries to guess the right options when it is installed. Therefore, you may want to start with one of the examples in the SWIG/Examples/perl5 directory. If that doesn't work, you will need to read the man-pages for your compiler and linker to get the right set of options. You might also -check the SWIG Wiki for +check the SWIG Wiki for additional information.

        @@ -208,7 +208,7 @@ the target should be named `example.so', `example.sl', or the appropriate dynamic module name on your system.

        -

        33.2.3 Building a dynamic module with MakeMaker

        +

        30.2.3 Building a dynamic module with MakeMaker

        @@ -242,7 +242,7 @@ the preferred approach to compilation. More information about MakeMaker can be found in "Programming Perl, 2nd ed." by Larry Wall, Tom Christiansen, and Randal Schwartz.

        -

        33.2.4 Building a static version of Perl

        +

        30.2.4 Building a static version of Perl

        @@ -311,7 +311,7 @@ added to it. Depending on your machine, you may need to link with additional libraries such as -lsocket, -lnsl, -ldl, etc.

        -

        33.2.5 Using the module

        +

        30.2.5 Using the module

        @@ -322,7 +322,7 @@ all goes well, you will be able to do this:

         $ perl
         use example;
        -print example::fact(4),"\n";
        +print example::fact(4), "\n";
         24
         
        @@ -464,7 +464,7 @@ system configuration (this requires root access and you will need to read the man pages).

        -

        33.2.6 Compilation problems and compiling with C++

        +

        30.2.6 Compilation problems and compiling with C++

        @@ -607,7 +607,7 @@ have to find the macro that conflicts and add an #undef into the .i file. Pleas any conflicting macros you find to swig-user mailing list.

        -

        33.2.7 Compiling for 64-bit platforms

        +

        30.2.7 Compiling for 64-bit platforms

        @@ -634,7 +634,7 @@ also introduce problems on platforms that support more than one linking standard (e.g., -o32 and -n32 on Irix).

        -

        33.3 Building Perl Extensions under Windows

        +

        30.3 Building Perl Extensions under Windows

        @@ -645,7 +645,7 @@ section assumes you are using SWIG with Microsoft Visual C++ although the procedure may be similar with other compilers.

        -

        33.3.1 Running SWIG from Developer Studio

        +

        30.3.1 Running SWIG from Developer Studio

        @@ -708,7 +708,7 @@ print "$a\n";

        -

        33.3.2 Using other compilers

        +

        30.3.2 Using other compilers

        @@ -716,7 +716,7 @@ SWIG is known to work with Cygwin and may work with other compilers on Windows. For general hints and suggestions refer to the Windows chapter.

        -

        33.4 The low-level interface

        +

        30.4 The low-level interface

        @@ -726,7 +726,7 @@ can be used to control your application. However, it is also used to construct more user-friendly proxy classes as described in the next section.

        -

        33.4.1 Functions

        +

        30.4.1 Functions

        @@ -749,7 +749,7 @@ use example; $a = &example::fact(2);

        -

        33.4.2 Global variables

        +

        30.4.2 Global variables

        @@ -770,7 +770,7 @@ is accessed as follows:

         use example;
        -print $example::Spam,"\n";
        +print $example::Spam, "\n";
         $example::Spam = $example::Spam + 4
         # ... etc ...
         
        @@ -819,7 +819,7 @@ extern char *path;       // Declared later in the input
         
        -

        33.4.3 Constants

        +

        30.4.3 Constants

        @@ -841,7 +841,7 @@ In Perl:

         use example;
        -print $example::FOO,"\n";    # OK
        +print $example::FOO, "\n";   # OK
         $example::FOO = 2;           # Error
         
        @@ -855,11 +855,11 @@ usually gives a more natural Perl interface, for example:
         use example;
        -print example::FOO,"\n";
        +print example::FOO, "\n";
         
        -

        33.4.4 Pointers

        +

        30.4.4 Pointers

        @@ -940,16 +940,16 @@ example: %inline %{ /* C-style cast */ Bar *FooToBar(Foo *f) { - return (Bar *) f; + return (Bar *) f; } /* C++-style cast */ Foo *BarToFoo(Bar *b) { - return dynamic_cast<Foo*>(b); + return dynamic_cast<Foo*>(b); } Foo *IncrFoo(Foo *f, int i) { - return f+i; + return f+i; } %}

        @@ -968,7 +968,7 @@ as XS and xsubpp. Given the advancement of the SWIG typesystem and the SWIG and XS, this is no longer supported.

        -

        33.4.5 Structures

        +

        30.4.5 Structures

        @@ -978,7 +978,7 @@ accessor functions as described in the "SWIG Basics" chapter. For example,

         struct Vector {
        -  double x,y,z;
        +  double x, y, z;
         };
         
        @@ -1004,8 +1004,8 @@ These functions are then used to access structure data from Perl as follows:
         $v = example::new_Vector();
        -print example::Vector_x_get($v),"\n";    # Get x component
        -example::Vector_x_set($v,7.8);          # Change x component
        +print example::Vector_x_get($v), "\n";   # Get x component
        +example::Vector_x_set($v, 7.8);          # Change x component
         

        @@ -1020,12 +1020,12 @@ can also be forced to be read-only using the %immutable directive. For

         struct Foo {
        -   ...
        -   %immutable;
        -   int x;        /* Read-only members */
        -   char *name;
        -   %mutable;
        -   ...
        +  ...
        +  %immutable;
        +  int x;        /* Read-only members */
        +  char *name;
        +  %mutable;
        +  ...
         };
         
        @@ -1045,7 +1045,7 @@ Array members are normally wrapped as read-only. For example,
         struct Foo {
        -   int  x[50];
        +  int x[50];
         };
         
        @@ -1057,7 +1057,7 @@ produces a single accessor function like this:
         int *Foo_x_get(Foo *self) {
        -    return self->x;
        +  return self->x;
         };
         
        @@ -1076,11 +1076,11 @@ When structure members are wrapped, they are handled as pointers. For example,
         struct Foo {
        -   ...
        +  ...
         };
         
         struct Bar {
        -   Foo f;
        +  Foo f;
         };
         
        @@ -1092,17 +1092,17 @@ generates accessor functions such as this:
         Foo *Bar_f_get(Bar *b) {
        -    return &b->f;
        +  return &b->f;
         }
         
         void Bar_f_set(Bar *b, Foo *val) {
        -    b->f = *val;
        +  b->f = *val;
         }
         
        -

        33.4.6 C++ classes

        +

        30.4.6 C++ classes

        @@ -1148,14 +1148,14 @@ In Perl, these functions are used in a straightforward manner:

         use example;
         $l = example::new_List();
        -example::List_insert($l,"Ale");
        -example::List_insert($l,"Stout");
        -example::List_insert($l,"Lager")
        +example::List_insert($l, "Ale");
        +example::List_insert($l, "Stout");
        +example::List_insert($l, "Lager")
         example::List_print($l)
         Lager
         Stout
         Ale
        -print example::List_length_get($l),"\n";
        +print example::List_length_get($l), "\n";
         3
         
        @@ -1167,7 +1167,7 @@ provides direct access to C++ objects. A higher level interface using Perl prox can be built using these low-level accessors. This is described shortly.

        -

        33.4.7 C++ classes and type-checking

        +

        30.4.7 C++ classes and type-checking

        @@ -1203,7 +1203,7 @@ If necessary, the type-checker also adjusts the value of the pointer (as is nece multiple inheritance is used).

        -

        33.4.8 C++ overloaded functions

        +

        30.4.8 C++ overloaded functions

        @@ -1222,9 +1222,9 @@ void foo(char *c); // Stays 'foo' (not renamed) class Spam { public: - void foo(int); // Becomes 'foo_i' - void foo(double); // Becomes 'foo_d' - ... + void foo(int); // Becomes 'foo_i' + void foo(double); // Becomes 'foo_d' + ... };

        @@ -1238,8 +1238,8 @@ Now, in Perl, the methods are accessed as follows: use example; example::foo_i(3); $s = example::new_Spam(); -example::Spam_foo_i($s,3); -example::Spam_foo_d($s,3.14); +example::Spam_foo_i($s, 3); +example::Spam_foo_d($s, 3.14);
        @@ -1247,7 +1247,7 @@ example::Spam_foo_d($s,3.14); Please refer to the "SWIG Basics" chapter for more information.

        -

        33.4.9 Operators

        +

        30.4.9 Operators

        @@ -1274,7 +1274,7 @@ The following C++ operators are currently supported by the Perl module:

      • operator or
      -

      33.4.10 Modules and packages

      +

      30.4.10 Modules and packages

      @@ -1286,7 +1286,7 @@ a single Perl module. The name of the module is determined by the

       $ perl5
       use example;                      # load the example module
      -print example::fact(4),"\n"       # Call a function in it
      +print example::fact(4), "\n"      # Call a function in it
       24
       
      @@ -1365,11 +1365,11 @@ all of the functions in that module will be installed into the package
       use example;   # Load the module like before
      -print Foo::fact(4),"\n";        # Call a function in package FooBar
      +print Foo::fact(4), "\n";        # Call a function in package FooBar
       
      --> -

      33.5 Input and output parameters

      +

      30.5 Input and output parameters

      @@ -1380,7 +1380,7 @@ example:

       void add(int x, int y, int *result) {
      -   *result = x + y;
      +  *result = x + y;
       }
       
      @@ -1392,7 +1392,7 @@ or perhaps
       int sub(int *x, int *y) {
      -   return *x+*y;
      +  return *x+*y;
       }
       
      @@ -1417,10 +1417,10 @@ In Perl, this allows you to pass simple values. For example:
      -$a = example::add(3,4);
      +$a = example::add(3, 4);
       print "$a\n";
       7
      -$b = example::sub(7,4);
      +$b = example::sub(7, 4);
       print "$b\n";
       3
       
      @@ -1456,7 +1456,7 @@ If a function mutates one of its parameters like this,
       void negate(int *x) {
      -   *x = -(*x);
      +  *x = -(*x);
       }
       
      @@ -1552,7 +1552,7 @@ Now, in Perl:
      -($r,$c) = example::get_dimensions($m);
      +($r, $c) = example::get_dimensions($m);
       
      @@ -1578,7 +1578,7 @@ In Perl:
       use example;
       $c = 0.0;
      -example::add(3,4,\$c);
      +example::add(3, 4, \$c);
       print "$c\n";
       7
       
      @@ -1588,7 +1588,7 @@ print "$c\n"; Note: The REFERENCE feature is only currently supported for numeric types (integers and floating point).

      -

      33.6 Exception handling

      +

      30.6 Exception handling

      @@ -1614,7 +1614,7 @@ class DoubleArray { } // Destroy an array ~DoubleArray() { - delete ptr; + delete ptr; } // Return the length of the array int length() { @@ -1633,9 +1633,8 @@ class DoubleArray { void setitem(int i, double val) { if ((i >= 0) && (i < n)) ptr[i] = val; - else { + else throw RangeError(); - } } };

      @@ -1753,7 +1752,7 @@ This is still supported, but it is deprecated. The newer %exception di functionality, but it has additional capabilities that make it more powerful.

      -

      33.7 Remapping datatypes with typemaps

      +

      30.7 Remapping datatypes with typemaps

      @@ -1770,7 +1769,7 @@ Typemaps are only used if you want to change some aspect of the primitive C-Perl interface.

      -

      33.7.1 A simple typemap example

      +

      30.7.1 A simple typemap example

      @@ -1830,7 +1829,7 @@ the typemap system follows typedef declarations. For example:

       %typemap(in) int n {
         $1 = (int) SvIV($input);
      -  printf("n = %d\n",$1);
      +  printf("n = %d\n", $1);
       }
       %inline %{
       typedef int Integer;
      @@ -1852,7 +1851,7 @@ Typemaps can also be defined for groups of consecutive arguments.  For example:
       
       %typemap(in) (char *str, unsigned len) {
      -    $1 = SvPV($input,$2);
      +    $1 = SvPV($input, $2);
       };
       
       int count(char c, char *str, unsigned len);
      @@ -1867,14 +1866,14 @@ parameter is omitted):
       
       
      -example::count("e","Hello World");
      +example::count("e", "Hello World");
       1
       >>>
       
      -

      33.7.2 Perl5 typemaps

      +

      30.7.2 Perl5 typemaps

      @@ -1888,9 +1887,9 @@ like this:

       %typemap(out) int {
      -    $result = sv_newmortal();
      -    set_setiv($result, (IV) $1);
      -    argvi++;
      +  $result = sv_newmortal();
      +  sv_setiv($result, (IV) $1);
      +  argvi++;
       }
       
      @@ -1979,7 +1978,7 @@ Return of C++ member data (all languages). Check value of input parameter.
      -

      33.7.3 Typemap variables

      +

      30.7.3 Typemap variables

      @@ -2050,7 +2049,7 @@ properly assigned. The Perl name of the wrapper function being created. -

      33.7.4 Useful functions

      +

      30.7.4 Useful functions

      @@ -2119,7 +2118,7 @@ int sv_isa(SV *, char *0; -

      33.8 Typemap Examples

      +

      30.8 Typemap Examples

      @@ -2128,7 +2127,7 @@ might look at the files "perl5.swg" and "typemaps.i" in the SWIG library.

      -

      33.8.1 Converting a Perl5 array to a char **

      +

      30.8.1 Converting a Perl5 array to a char **

      @@ -2156,7 +2155,7 @@ reference to be used as a char ** datatype. $1 = (char **) malloc((len+2)*sizeof(char *)); for (i = 0; i <= len; i++) { tv = av_fetch(tempav, i, 0); - $1[i] = (char *) SvPV(*tv,PL_na); + $1[i] = (char *) SvPV(*tv, PL_na); } $1[i] = NULL; }; @@ -2170,16 +2169,16 @@ reference to be used as a char ** datatype. %typemap(out) char ** { AV *myav; SV **svs; - int i = 0,len = 0; + int i = 0, len = 0; /* Figure out how many elements we have */ while ($1[len]) - len++; + len++; svs = (SV **) malloc(len*sizeof(SV *)); for (i = 0; i < len ; i++) { - svs[i] = sv_newmortal(); - sv_setpv((SV*)svs[i],$1[i]); + svs[i] = sv_newmortal(); + sv_setpv((SV*)svs[i], $1[i]); }; - myav = av_make(len,svs); + myav = av_make(len, svs); free(svs); $result = newRV_noinc((SV*)myav); sv_2mortal($result); @@ -2188,20 +2187,20 @@ reference to be used as a char ** datatype. // Now a few test functions %inline %{ -int print_args(char **argv) { + int print_args(char **argv) { int i = 0; while (argv[i]) { - printf("argv[%d] = %s\n", i,argv[i]); - i++; + printf("argv[%d] = %s\n", i, argv[i]); + i++; } return i; -} + } -// Returns a char ** list -char **get_args() { + // Returns a char ** list + char **get_args() { static char *values[] = { "Dave", "Mike", "Susan", "John", "Michelle", 0}; return &values[0]; -} + } %}

      @@ -2216,11 +2215,11 @@ use argv; @a = ("Dave", "Mike", "John", "Mary"); # Create an array of strings argv::print_args(\@a); # Pass it to our C function $b = argv::get_args(); # Get array of strings from C -print @$b,"\n"; # Print it out +print @$b, "\n"; # Print it out -

      33.8.2 Return values

      +

      30.8.2 Return values

      @@ -2241,15 +2240,15 @@ can be done using the EXTEND() macro as in:

       %typemap(argout) int *OUTPUT {
         if (argvi >= items) {
      -    EXTEND(sp,1);              /* Extend the stack by 1 object */
      +    EXTEND(sp, 1);              /* Extend the stack by 1 object */
         }
         $result = sv_newmortal();
      -  sv_setiv($target,(IV) *($1));
      +  sv_setiv($target, (IV) *($1));
         argvi++;
       }
       
      -

      33.8.3 Returning values from arguments

      +

      30.8.3 Returning values from arguments

      @@ -2271,7 +2270,7 @@ its arguments. This example describes the implementation of the OUTPUT // We don't care what the input value is. Ignore, but set to a temporary variable -%typemap(in,numinputs=0) double *OUTPUT(double junk) { +%typemap(in, numinputs=0) double *OUTPUT(double junk) { $1 = &junk; } @@ -2298,12 +2297,12 @@ For example:

      -@r = multout(7,13);
      -print "multout(7,13) = @r\n";
      -($x,$y) = multout(7,13);
      +@r = multout(7, 13);
      +print "multout(7, 13) = @r\n";
      +($x, $y) = multout(7, 13);
       
      -

      33.8.4 Accessing array structure members

      +

      30.8.4 Accessing array structure members

      @@ -2313,8 +2312,8 @@ Consider the following data structure:

       #define SIZE  8
       typedef struct {
      -    int   values[SIZE];
      -    ...
      +  int   values[SIZE];
      +  ...
       } Foo;
       
       
      @@ -2328,10 +2327,10 @@ To make the member writable, a "memberin" typemap can be used.
       %typemap(memberin) int [SIZE] {
      -    int i;
      -    for (i = 0; i < SIZE; i++) {
      -        $1[i] = $input[i];
      -    }
      +  int i;
      +  for (i = 0; i < SIZE; i++) {
      +    $1[i] = $input[i];
      +  }
       }
       
       
      @@ -2349,10 +2348,10 @@ For example:
       %typemap(memberin) int [ANY] {
      -   int i;
      -   for (i = 0; i < $1_dim0; i++) {
      -      $1[i] = $input[i];
      -   }
      +  int i;
      +  for (i = 0; i < $1_dim0; i++) {
      +    $1[i] = $input[i];
      +  }
       }
       
      @@ -2366,7 +2365,7 @@ the "in" typemap in the previous section would be used to convert an to copy the converted array into a C data structure.

      -

      33.8.5 Turning Perl references into C pointers

      +

      30.8.5 Turning Perl references into C pointers

      @@ -2390,7 +2389,7 @@ A common misinterpretation of this function is the following Perl script: $a = 3.5; $b = 7.5; $c = 0.0; # Output value -add($a,$b,\$c); # Place result in c (Except that it doesn't work) +add($a, $b, \$c); # Place result in c (Except that it doesn't work)

      @@ -2426,12 +2425,12 @@ Now, if you place this before the add function, you can do this: $a = 3.5; $b = 7.5; $c = 0.0; -add($a,$b,\$c); # Now it works! +add($a, $b, \$c); # Now it works! print "$c\n"; -

      33.8.6 Pointer handling

      +

      30.8.6 Pointer handling

      @@ -2477,7 +2476,9 @@ is usually accessed as follows:

       Foo *f;
      -if (SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0) == -1) return NULL;
      +if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0))) {
      +  SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
      +}
       
       SV *sv = sv_newmortal();
       SWIG_MakePtr(sv, f, SWIGTYPE_p_Foo, 0);
      @@ -2492,7 +2493,9 @@ variable $1_descriptor.  For example:
       
       %typemap(in) Foo * {
      -   if ((SWIG_ConvertPtr($input,(void **) &$1, $1_descriptor,0)) == -1) return NULL;
      +  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
      +    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
      +  }
       }
       
      @@ -2505,12 +2508,14 @@ For example:
       %typemap(in) Foo * {
      -   if ((SWIG_ConvertPtr($input,(void **) &$1, $descriptor(Foo *), 0)) == -1) return NULL;
      +  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $descriptor(Foo *), 0))) {
      +    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
      +  }
       }
       
      -

      33.9 Proxy classes

      +

      30.9 Proxy classes

      @@ -2526,7 +2531,7 @@ to the underlying code. This section describes the implementation details of the proxy interface.

      -

      33.9.1 Preliminaries

      +

      30.9.1 Preliminaries

      @@ -2548,7 +2553,7 @@ SWIG creates a collection of high-level Perl wrappers. In your scripts, you wil high level wrappers. The wrappers, in turn, interact with the low-level procedural module.

      -

      33.9.2 Structure and class wrappers

      +

      30.9.2 Structure and class wrappers

      @@ -2560,7 +2565,7 @@ Suppose you have the following SWIG interface file: struct Vector { Vector(double x, double y, double z); ~Vector(); - double x,y,z; + double x, y, z; };

      @@ -2594,48 +2599,48 @@ package example::Vector; %BLESSEDMEMBERS = (); sub new () { - my $self = shift; - my @args = @_; - $self = vectorc::new_Vector(@args); - return undef if (!defined($self)); - bless $self, "example::Vector"; - $OWNER{$self} = 1; - my %retval; - tie %retval, "example::Vector", $self; - return bless \%retval,"Vector"; + my $self = shift; + my @args = @_; + $self = vectorc::new_Vector(@args); + return undef if (!defined($self)); + bless $self, "example::Vector"; + $OWNER{$self} = 1; + my %retval; + tie %retval, "example::Vector", $self; + return bless \%retval, "Vector"; } sub DESTROY { - return unless $_[0]->isa('HASH'); - my $self = tied(%{$_[0]}); - delete $ITERATORS{$self}; - if (exists $OWNER{$self}) { - examplec::delete_Vector($self)); - delete $OWNER{$self}; - } + return unless $_[0]->isa('HASH'); + my $self = tied(%{$_[0]}); + delete $ITERATORS{$self}; + if (exists $OWNER{$self}) { + examplec::delete_Vector($self)); + delete $OWNER{$self}; + } } sub FETCH { - my ($self,$field) = @_; - my $member_func = "vectorc::Vector_${field}_get"; - my $val = &$member_func($self); - if (exists $BLESSEDMEMBERS{$field}) { - return undef if (!defined($val)); - my %retval; - tie %retval,$BLESSEDMEMBERS{$field},$val; - return bless \%retval, $BLESSEDMEMBERS{$field}; - } - return $val; + my ($self, $field) = @_; + my $member_func = "vectorc::Vector_${field}_get"; + my $val = &$member_func($self); + if (exists $BLESSEDMEMBERS{$field}) { + return undef if (!defined($val)); + my %retval; + tie %retval, $BLESSEDMEMBERS{$field}, $val; + return bless \%retval, $BLESSEDMEMBERS{$field}; + } + return $val; } sub STORE { - my ($self,$field,$newval) = @_; - my $member_func = "vectorc::Vector_${field}_set"; - if (exists $BLESSEDMEMBERS{$field}) { - &$member_func($self,tied(%{$newval})); - } else { - &$member_func($self,$newval); - } + my ($self, $field, $newval) = @_; + my $member_func = "vectorc::Vector_${field}_set"; + if (exists $BLESSEDMEMBERS{$field}) { + &$member_func($self, tied(%{$newval})); + } else { + &$member_func($self, $newval); + } } @@ -2656,8 +2661,8 @@ To use our new proxy class we can simply do the following:
       # Perl code using Vector class
      -$v = new Vector(2,3,4);
      -$w = Vector->new(-1,-2,-3);
      +$v = new Vector(2, 3, 4);
      +$w = Vector->new(-1, -2, -3);
       
       # Assignment of a single member
       $v->{x} = 7.5;
      @@ -2675,7 +2680,7 @@ $v->DESTROY();
       
       
      -

      33.9.3 Object Ownership

      +

      30.9.3 Object Ownership

      @@ -2700,7 +2705,7 @@ Vector object:

       Vector *new_Vector(double x, double y, double z) {
         Vector *v;
      -  v = new Vector(x,y,z);        // Call C++ constructor
      +  v = new Vector(x, y, z);        // Call C++ constructor
         return v;
       }
       
      @@ -2741,7 +2746,7 @@ done using the DISOWN method.
       # Perl code to change ownership of an object
      -$v = new Vector(x,y,z);
      +$v = new Vector(x, y, z);
       $v->DISOWN();     
       
      @@ -2762,7 +2767,7 @@ counting, garbage collection, or advanced features one might find in sophisticated languages.

      -

      33.9.4 Nested Objects

      +

      30.9.4 Nested Objects

      @@ -2815,7 +2820,7 @@ $p->{f}->{x} = 0.0; %${$p->{v}} = ( x=>0, y=>0, z=>0); -

      33.9.5 Proxy Functions

      +

      30.9.5 Proxy Functions

      @@ -2836,11 +2841,11 @@ this:

       sub dot_product {
      -    my @args = @_;
      -    $args[0] = tied(%{$args[0]});         # Get the real pointer values
      -    $args[1] = tied(%{$args[1]});
      -    my $result = vectorc::dot_product(@args);
      -    return $result;
      +  my @args = @_;
      +  $args[0] = tied(%{$args[0]});         # Get the real pointer values
      +  $args[1] = tied(%{$args[1]});
      +  my $result = vectorc::dot_product(@args);
      +  return $result;
       }
       
      @@ -2849,7 +2854,7 @@ This function replaces the original function, but operates in an identical manner.

      -

      33.9.6 Inheritance

      +

      30.9.6 Inheritance

      @@ -2925,7 +2930,7 @@ particular, inheritance of data members is extremely tricky (and I'm not even sure if it really works).

      -

      33.9.7 Modifying the proxy methods

      +

      30.9.7 Modifying the proxy methods

      @@ -2953,7 +2958,7 @@ public: }; -

      33.10 Adding additional Perl code

      +

      30.10 Adding additional Perl code

      @@ -2979,7 +2984,7 @@ sub set_transform for (my $j = 0; $j < 4, $j++) { mat44_set($a, $i, $j, $x->[i][j]) - } + } } example.set_transform($im, $a); free_mat44($a); @@ -2996,15 +3001,15 @@ low-level helper functions. For example, this code now seems to work:

       my $a =
      -  [[1,0,0,0],
      -   [0,1,0,0],
      -   [0,0,1,0],
      -   [0,0,0,1]];
      +  [[1, 0, 0, 0],
      +  [0, 1, 0, 0],
      +  [0, 0, 1, 0],
      +  [0, 0, 0, 1]];
       set_transform($im, $a);
       
      -

      33.11 Cross language polymorphism

      +

      30.11 Cross language polymorphism

      @@ -3038,7 +3043,7 @@ proxy classes, director classes, and C wrapper functions takes care of all the cross-language method routing transparently.

      -

      33.11.1 Enabling directors

      +

      30.11.1 Enabling directors

      @@ -3065,7 +3070,7 @@ globally, to specific classes, and to specific methods, like this: // generate directors for all classes that have virtual methods %feature("director"); -// generate directors for all virtual methods in class Foo +// generate directors for the virtual methods in class Foo %feature("director") Foo; @@ -3083,7 +3088,7 @@ directors for specific classes or methods. So for example,

      -will generate directors for all virtual methods of class Foo except +will generate directors for the virtual methods of class Foo except bar().

      @@ -3098,14 +3103,14 @@ the methods one() and two() (but not three()): %feature("director") Foo; class Foo { public: - Foo(int foo); - virtual void one(); - virtual void two(); + Foo(int foo); + virtual void one(); + virtual void two(); }; class Bar: public Foo { public: - virtual void three(); + virtual void three(); }; @@ -3128,7 +3133,7 @@ sub one { -

      33.11.2 Director classes

      +

      30.11.2 Director classes

      @@ -3148,7 +3153,8 @@ For simplicity let's ignore the Swig::Director class and refer to the original C++ class as the director's base class. By default, a director class extends all virtual methods in the inheritance chain of its base class (see the preceding section for how to modify this behavior). -Thus all virtual method calls, whether they originate in C++ or in +Virtual methods that have a final specifier are unsurprisingly excluded. +Thus the virtual method calls, whether they originate in C++ or in Perl via proxy classes, eventually end up in at the implementation in the director class. The job of the director methods is to route these method calls to the appropriate place in the inheritance chain. By @@ -3208,7 +3214,7 @@ so there is no need for the extra overhead involved with routing the calls through Perl.

      -

      33.11.3 Ownership and object destruction

      +

      30.11.3 Ownership and object destruction

      @@ -3257,7 +3263,7 @@ sub DESTROY { -

      33.11.4 Exception unrolling

      +

      30.11.4 Exception unrolling

      @@ -3273,9 +3279,9 @@ suffice in most cases:

       %feature("director:except") {
      -    if ($error != NULL) {
      -        throw Swig::DirectorMethodException();
      -    }
      +  if ($error != NULL) {
      +    throw Swig::DirectorMethodException();
      +  }
       }
       
      @@ -3299,8 +3305,8 @@ suitable exception handler:
       %exception {
      -    try { $action }
      -    catch (Swig::DirectorException &e) { SWIG_fail; }
      +  try { $action }
      +  catch (Swig::DirectorException &e) { SWIG_fail; }
       }
       
      @@ -3313,7 +3319,7 @@ Swig::DirectorMethodException is thrown, Perl will register the exception as soon as the C wrapper function returns.

      -

      33.11.5 Overhead and code bloat

      +

      30.11.5 Overhead and code bloat

      @@ -3347,7 +3353,7 @@ directive) for only those methods that are likely to be extended in Perl.

      -

      33.11.6 Typemaps

      +

      30.11.6 Typemaps

      diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 8c483b7a0..d0ec0df7f 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -7,7 +7,7 @@ -

      34 SWIG and PHP

      +

      31 SWIG and PHP

        @@ -50,27 +50,17 @@

        -SWIG supports generating wrappers for PHP5. Support for PHP4 was removed -in SWIG 1.3.37. The PHP developers are no longer making new PHP4 releases, -and won't even be patching critical security issues after 2008-08-08, so it -doesn't make much sense for SWIG to continue to support PHP4 now. If you -really need to continue to use PHP4, just stick with SWIG 1.3.36. +In this chapter, we discuss SWIG's support of PHP. SWIG currently supports +generating wrappers for PHP7. Support for PHP5 was removed in SWIG 4.0.0 +and support for PHP4 was removed in SWIG 1.3.37.

        -Currently any PHP5 release should work, but we don't regularly test with -PHP < 5.3. +Currently any PHP7 release should work.

        -In this chapter, we discuss SWIG's support of PHP. The PHP module -was extensively rewritten in release 1.3.26, and support for generating -OO wrappers for PHP5 was added in 1.3.30. The PHP module now supports most -of the features available in some of the other languages. -

        - -

        -In order to use this module, you will need to have a copy of the PHP5 +In order to use this module, you will need to have a copy of the PHP include files to compile the SWIG generated files. If you installed PHP from a binary package, you may need to install a "php-dev" or "php-devel" package for these to be installed. You can find out where these files are @@ -80,16 +70,17 @@ your extension into php directly, you will need the complete PHP source tree available.

        -

        34.1 Generating PHP Extensions

        +

        31.1 Generating PHP Extensions

        -To build a PHP extension, run swig using the -php option as -follows: +To build a PHP extension, run swig using the -php7 option as follows +(-php is also supported and currently is an alias for -php7 +but prior to SWIG 4.0.0 it was an alias for -php5):

        -swig -php example.i
        +swig -php7 example.i
         

        @@ -102,13 +93,16 @@ The third file, example.php can be included by PHP scripts. It attempts to dynamically load the extension and contains extra php code specified in the interface file. If wrapping C++ code with PHP classes, it will -also contain PHP5 class wrappers. +also contain PHP class wrappers.

        SWIG can generate PHP extensions from C++ libraries as well when given the -c++ option. The support for C++ is discussed in -more detail in section 27.2.6. +more detail in section 27.2.6. The generated +C++ wrapper will be called example_wrap.cxx. You can specify a +different extension for the C++ wrapper using -cppext - +e.g. if you want example_wrap.cc use -cppext cc.

        @@ -125,7 +119,7 @@ and it doesn't play nicely with package system. We don't recommend this approach, or provide explicit support for it.

        -

        34.1.1 Building a loadable extension

        +

        31.1.1 Building a loadable extension

        @@ -140,7 +134,7 @@ least work for Linux though): gcc -shared example_wrap.o example.o -o example.so

      -

      34.1.2 Using PHP Extensions

      +

      31.1.2 Using PHP Extensions

      @@ -159,8 +153,8 @@ If the module is in PHP's default extension directory, you can omit the path.

      For some SAPIs (for example, the CLI SAPI) you can instead use the -dl() function to load -an extension at run time, by adding a like like this to the start of each +dl() function to load +an extension at run time, by adding a line like this to the start of each PHP script which uses your extension:

      @@ -169,8 +163,8 @@ PHP script which uses your extension:

      -But note that this doesn't work when running PHP through a webserver in PHP5.3 -and later - you'll need to use extension in php.ini as +But note that dl() isn't supported when running PHP through a +webserver - you'll need to use extension in php.ini as described above.

      @@ -188,7 +182,7 @@ This PHP module also defines the PHP classes for the wrapped API, so you'll almost certainly want to include it anyway.

      -

      34.2 Basic PHP interface

      +

      31.2 Basic PHP interface

      @@ -196,10 +190,11 @@ It is important to understand that PHP uses a single global namespace into which all symbols from extension modules are loaded. It is quite possible for names of symbols in one extension module to clash with other symbols unless care is taken to %rename them. At present -SWIG doesn't have support for the namespace feature added in PHP 5.3. +SWIG doesn't have support for generating wrappers which make use of PHP's +namespace feature.

      -

      34.2.1 Constants

      +

      31.2.1 Constants

      @@ -236,10 +231,12 @@ echo "E = " . E . "\n";

      There's one peculiarity of how constants work in PHP which it is useful to note (this is not specific to SWIG though) - if you try to use an undeclared -constant, PHP will emit a notice and then expand the constant to a string -version of the constant's name. Unfortunately it is easy to miss the notice -if you're using PHP in a webserver, as it will probably end up in error.log or -similar. +constant, PHP will emit a warning (or a notice in PHP 7.1 and earlier) and then +expand the constant to a string version of the constant's name. Unfortunately +it is easy to miss the warning message if you're using PHP in a webserver as +it will probably end up in error.log or similar. Apparently this will throw +an Error in a future version of PHP, but until then it's something to be +aware of.

      @@ -276,7 +273,7 @@ is treated as true by the if test, when the value of the intended constant would be treated as false!

      -

      34.2.2 Global Variables

      +

      31.2.2 Global Variables

      @@ -291,7 +288,7 @@ the use of automatically generated accessor functions. %inline %{ double seki = 2; void print_seki() { - zend_printf("seki is now %f\n",seki); + zend_printf("seki is now %f\n", seki); } %} @@ -325,7 +322,7 @@ undefined. At this time SWIG does not support custom accessor methods.

      -

      34.2.3 Functions

      +

      31.2.3 Functions

      @@ -378,7 +375,7 @@ print $s; # The value of $s was not changed. --> -

      34.2.4 Overloading

      +

      31.2.4 Overloading

      @@ -386,8 +383,7 @@ Although PHP does not support overloading functions natively, swig will generate dispatch functions which will use %typecheck typemaps to allow overloading. This dispatch function's operation and precedence is described in Wrapping -Overloaded Functions and Methods. +href="SWIGPlus.html#SWIGPlus_overloaded_methods">Overloaded functions and methods.

      -

      34.2.5 Pointers and References

      +

      31.2.5 Pointers and References

      @@ -459,7 +455,7 @@ One can include cpointer.i to generate PHP wrappers to int

       %module example
       %include "cpointer.i"
      -%pointer_functions(int,intp)
      +%pointer_functions(int, intp)
       
       void add( int *in1, int *in2, int *result);
       
      @@ -509,7 +505,7 @@ include("example.php"); $in1 = 3; $in2 = 5; -$result= add($in1,$in2); # Note using variables for the input is unnecessary. +$result= add($in1, $in2); # Note using variables for the input is unnecessary. echo "The sum $in1 + $in2 = $result\n"; ?> @@ -522,13 +518,6 @@ this, one needs to include phppointers.i which defines the named typemap REF.

      -

      -Prior to SWIG 3.0, the REF typemaps relied on PHP's call-time -pass-by-reference, which was deprecated in PHP 5.3 and removed in PHP 5.4. -So if you use these REF typemaps, you should ensure that SWIG≥3.0 is -used to generate wrappers from your interface file. -

      -

      In case you write your own typemaps, SWIG supports an attribute called byref: if you set that, then SWIG will make sure that the generated @@ -555,7 +544,7 @@ include("example.php"); $in1 = 3; $in2 = 5; $result = 0; -add($in1,$in2,$result); +add($in1, $in2, $result); echo "The sum $in1 + $in2 = $result\n"; ?> @@ -579,7 +568,7 @@ PHP in a number of ways: by using unset on an existing variable, or assigning NULL to a variable.

      -

      34.2.6 Structures and C++ classes

      +

      31.2.6 Structures and C++ classes

      @@ -599,7 +588,7 @@ This interface file class Vector { public: - double x,y,z; + double x, y, z; Vector(); ~Vector(); double magnitude(); @@ -611,7 +600,7 @@ struct Complex {

      -Would be used in the following way from PHP5: +Would be used in the following way from PHP:

      @@ -623,7 +612,7 @@ Would be used in the following way from PHP5:
         $v->y = 4;
         $v->z = 5;
       
      -  echo "Magnitude of ($v->x,$v->y,$v->z) = " . $v->magnitude() . "\n";
      +  echo "Magnitude of ($v->x, $v->y, $v->z) = " . $v->magnitude() . "\n";
       
         $v = NULL;   # destructor called.
       
      @@ -640,33 +629,33 @@ Would be used in the following way from PHP5:
       Member variables and methods are accessed using the -> operator.
       

      -

      34.2.6.1 Using -noproxy

      +

      31.2.6.1 Using -noproxy

      The -noproxy option flattens the object structure and generates collections of named functions (these are the functions -which the PHP5 class wrappers call). The above example results +which the PHP class wrappers call). The above example results in the following PHP functions:

       new_Vector();
      -Vector_x_set($obj,$d);
      +Vector_x_set($obj, $d);
       Vector_x_get($obj);
      -Vector_y_set($obj,$d);
      +Vector_y_set($obj, $d);
       Vector_y_get($obj);
      -Vector_z_set($obj,$d);
      +Vector_z_set($obj, $d);
       Vector_z_get($obj);
       Vector_magnitude($obj);
       new_Complex();
      -Complex_re_set($obj,$d);
      +Complex_re_set($obj, $d);
       Complex_re_get($obj);
      -Complex_im_set($obj,$d);
      +Complex_im_set($obj, $d);
       Complex_im_get($obj);
       
      -

      34.2.6.2 Constructors and Destructors

      +

      31.2.6.2 Constructors and Destructors

      @@ -707,7 +696,7 @@ the programmer can either reassign the variable or call unset($v)

      -

      34.2.6.3 Static Member Variables

      +

      31.2.6.3 Static Member Variables

      @@ -750,7 +739,7 @@ Ko::threats(10); echo "There have now been " . Ko::threats() . " threats\n";

      -

      34.2.6.4 Static Member Functions

      +

      31.2.6.4 Static Member Functions

      @@ -772,7 +761,7 @@ Ko::threats(); -

      34.2.6.5 Specifying Implemented Interfaces

      +

      31.2.6.5 Specifying Implemented Interfaces

      @@ -790,7 +779,7 @@ so: If there are multiple interfaces, just list them separated by commas.

      -

      34.2.7 PHP Pragmas, Startup and Shutdown code

      +

      31.2.7 PHP Pragmas, Startup and Shutdown code

      @@ -816,6 +805,15 @@ Results in the following in "example.php" echo "example.php execution\n"; +

      +The version pragma can be used to add version to generated PHP extension module. The version is inserted in the zend_module_entry block. +

      + +
      +%module example
      +%pragma(php) version="1.5"
      +
      +

      The include pragma is a short cut to add include statements to the example.php file. @@ -878,7 +876,7 @@ The %rinit and %rshutdown statements are very similar but inse into the request init (PHP_RINIT_FUNCTION) and request shutdown (PHP_RSHUTDOWN_FUNCTION) code respectively.

      -

      34.3 Cross language polymorphism

      +

      31.3 Cross language polymorphism

      @@ -913,7 +911,7 @@ wrapper functions takes care of all the cross-language method routing transparently.

      -

      34.3.1 Enabling directors

      +

      31.3.1 Enabling directors

      @@ -940,7 +938,7 @@ globally, to specific classes, and to specific methods, like this: // generate directors for all classes that have virtual methods %feature("director"); -// generate directors for all virtual methods in class Foo +// generate directors for the virtual methods in class Foo %feature("director") Foo; @@ -958,7 +956,7 @@ directors for specific classes or methods. So for example,

      -will generate directors for all virtual methods of class Foo except +will generate directors for the virtual methods of class Foo except bar().

      @@ -973,14 +971,14 @@ the methods one() and two() (but not three()): %feature("director") Foo; class Foo { public: - Foo(int foo); - virtual void one(); - virtual void two(); + Foo(int foo); + virtual void one(); + virtual void two(); }; class Bar: public Foo { public: - virtual void three(); + virtual void three(); }; @@ -995,14 +993,14 @@ require("mymodule.php"); class MyFoo extends Foo { function one() { - print "one from php\n"; + print "one from php\n"; } } -

      34.3.2 Director classes

      +

      31.3.2 Director classes

      @@ -1023,7 +1021,8 @@ For simplicity let's ignore the Swig::Director class and refer to the original C++ class as the director's base class. By default, a director class extends all virtual methods in the inheritance chain of its base class (see the preceding section for how to modify this behavior). -Thus all virtual method calls, whether they originate in C++ or in +Virtual methods that have a final specifier are unsurprisingly excluded. +Thus the virtual method calls, whether they originate in C++ or in PHP via proxy classes, eventually end up in at the implementation in the director class. The job of the director methods is to route these method calls to the appropriate place in the inheritance chain. By "appropriate @@ -1082,7 +1081,7 @@ so there is no need for the extra overhead involved with routing the calls through PHP.

      -

      34.3.3 Ownership and object destruction

      +

      31.3.3 Ownership and object destruction

      @@ -1112,12 +1111,12 @@ Here is an example:

       class Foo {
       public:
      -    ...
      +  ...
       };
       class FooContainer {
       public:
      -    void addFoo(Foo *);
      -    ...
      +  void addFoo(Foo *);
      +  ...
       };
       
      @@ -1138,25 +1137,33 @@ In this example, we are assuming that FooContainer will take care of deleting all the Foo pointers it contains at some point.

      -

      34.3.4 Exception unrolling

      +

      31.3.4 Exception unrolling

      With directors routing method calls to PHP, and proxies routing them -to C++, the handling of exceptions is an important concern. By default, the -directors ignore exceptions that occur during method calls that are -resolved in PHP. To handle such exceptions correctly, it is necessary -to temporarily translate them into C++ exceptions. This can be done with -the %feature("director:except") directive. The following code should -suffice in most cases: +to C++, the handling of exceptions is an important concern. By default, an +exception thrown in PHP code called from C++ causes the PHP interpreter +to flag that an exception is thrown, then return passes to C++ as if +the PHP function had returned Null. Assuming the directorout +typemaps handle this (those SWIG defines by default should) then once +control returns to PHP code again, the PHP exception will actually propagate. +

      + +

      +Sometimes this control flow is problematic, and you want to skip any +handling in the C++ code. To achieve this, it is necessary +to temporarily translate the PHP exception into a C++ exception. This can be +achieved using the %feature("director:except") directive. The following code +should suffice in most cases:

       %feature("director:except") {
      -    if ($error == FAILURE) {
      -        throw Swig::DirectorMethodException();
      -    }
      +  if ($error == FAILURE) {
      +    throw Swig::DirectorMethodException();
      +  }
       }
       
      @@ -1183,8 +1190,8 @@ suitable exception handler:
       %exception {
      -    try { $action }
      -    catch (Swig::DirectorException &e) { SWIG_fail; }
      +  try { $action }
      +  catch (Swig::DirectorException &e) { SWIG_fail; }
       }
       
      @@ -1197,7 +1204,7 @@ Swig::DirectorMethodException is thrown, PHP will register the exception as soon as the C wrapper function returns.

      -

      34.3.5 Overhead and code bloat

      +

      31.3.5 Overhead and code bloat

      @@ -1230,7 +1237,7 @@ optimized by selectively enabling director methods (using the %feature directive) for only those methods that are likely to be extended in PHP.

      -

      34.3.6 Typemaps

      +

      31.3.6 Typemaps

      @@ -1244,7 +1251,7 @@ need to be supported.

      -

      34.3.7 Miscellaneous

      +

      31.3.7 Miscellaneous

      Director typemaps for STL classes are mostly in place, and hence you diff --git a/Doc/Manual/Pike.html b/Doc/Manual/Pike.html index 22ab4e2a2..2b8432399 100644 --- a/Doc/Manual/Pike.html +++ b/Doc/Manual/Pike.html @@ -7,7 +7,7 @@ -

      35 SWIG and Pike

      +

      37 SWIG and Pike

      -

      35.2 Basic C/C++ Mapping

      +

      37.2 Basic C/C++ Mapping

      -

      35.2.1 Modules

      +

      37.2.1 Modules

      @@ -144,7 +144,7 @@ concerned), SWIG's %module directive doesn't really have any significance.

      -

      35.2.2 Functions

      +

      37.2.2 Functions

      @@ -169,7 +169,7 @@ exactly as you'd expect it to: (1) Result: 24 -

      35.2.3 Global variables

      +

      37.2.3 Global variables

      @@ -198,7 +198,7 @@ will result in two functions, Foo_get() and Foo_set(): (3) Result: 3.141590 -

      35.2.4 Constants and enumerated types

      +

      37.2.4 Constants and enumerated types

      @@ -206,7 +206,7 @@ Enumerated types in C/C++ declarations are wrapped as Pike constants, not as Pike enums.

      -

      35.2.5 Constructors and Destructors

      +

      37.2.5 Constructors and Destructors

      @@ -214,7 +214,7 @@ Constructors are wrapped as create() methods, and destructors are wrapped as destroy() methods, for Pike classes.

      -

      35.2.6 Static Members

      +

      37.2.6 Static Members

      @@ -230,8 +230,8 @@ For example, given this C++ class declaration: class Shape { public: - static void print(); - static int nshapes; + static void print(); + static int nshapes; }; diff --git a/Doc/Manual/Preface.html b/Doc/Manual/Preface.html index 3b654a6d2..36a99bd1f 100644 --- a/Doc/Manual/Preface.html +++ b/Doc/Manual/Preface.html @@ -69,6 +69,9 @@ over a period of 10 years starting from the year 2000. The final version in the series was 1.3.40, but in truth the 1.3.x series had been stable for many years. An official stable version was released along with the decision to make SWIG license changes and this gave rise to version 2.0.0 in 2010. +Version 3.0.0 was released in 2014 focusing on adding C++11 support and C++ nested classes. +Version 4.0.0 was released in 2019 to add in Doxygen support. +Some target languages were disabled as part of a clean up and others were given a new status of either 'Supported' or 'Experimental'.

      1.3 SWIG License

      @@ -364,7 +367,7 @@ a number of packages to be installed. Full instructions at

      SWIG is known to work on various flavors of OS X. Follow the Unix installation instructions above. However, as of this writing, there is still great deal of -inconsistency with how shared libaries are handled by various scripting languages +inconsistency with how shared libraries are handled by various scripting languages on OS X.

      @@ -435,7 +438,7 @@ don't intend to use these features in your own programs.

      -Note: The test-suite currently contains over 500 tests. If you +Note: The test-suite currently contains over 600 tests. If you have many different target languages installed and a slow machine, it might take more than an hour to run the test-suite.

      diff --git a/Doc/Manual/Preprocessor.html b/Doc/Manual/Preprocessor.html index 2538f8f18..3d1bb453e 100644 --- a/Doc/Manual/Preprocessor.html +++ b/Doc/Manual/Preprocessor.html @@ -7,7 +7,7 @@ -

      8 Preprocessing

      +

      10 Preprocessing

        @@ -38,7 +38,7 @@ However, a number of modifications and enhancements have been made. This chapter describes some of these modifications.

        -

        8.1 File inclusion

        +

        10.1 File inclusion

        @@ -64,7 +64,7 @@ By default, the #include is ignored unless you run SWIG with the is that you often don't want SWIG to try and wrap everything included in standard header system headers and auxiliary files. -

        8.2 File imports

        +

        10.2 File imports

        @@ -93,7 +93,7 @@ The -importall directive tells SWIG to follow all #include sta as imports. This might be useful if you want to extract type definitions from system header files without generating any wrappers. -

        8.3 Conditional Compilation

        +

        10.3 Conditional Compilation

        @@ -109,10 +109,6 @@ SWIGIMPORTED Defined when SWIG is importing a file with % SWIG_VERSION Hexadecimal (binary-coded decimal) number containing SWIG version, such as 0x010311 (corresponding to SWIG-1.3.11). -SWIGALLEGROCL Defined when using Allegro CL -SWIGCFFI Defined when using CFFI -SWIGCHICKEN Defined when using CHICKEN -SWIGCLISP Defined when using CLISP SWIGCSHARP Defined when using C# SWIGGUILE Defined when using Guile SWIGJAVA Defined when using Java @@ -120,18 +116,16 @@ SWIGJAVASCRIPT Defined when using Javascript SWIG_JAVASCRIPT_JSC Defined when using Javascript for JavascriptCore SWIG_JAVASCRIPT_V8 Defined when using Javascript for v8 or node.js SWIGLUA Defined when using Lua -SWIGMODULA3 Defined when using Modula-3 SWIGMZSCHEME Defined when using Mzscheme -SWIGOCAML Defined when using Ocaml +SWIGOCAML Defined when using OCaml SWIGOCTAVE Defined when using Octave SWIGPERL Defined when using Perl -SWIGPHP Defined when using PHP -SWIGPIKE Defined when using Pike +SWIGPHP Defined when using PHP (any version) +SWIGPHP7 Defined when using PHP7 SWIGPYTHON Defined when using Python SWIGR Defined when using R SWIGRUBY Defined when using Ruby SWIGSCILAB Defined when using Scilab -SWIGSEXP Defined when using S-expressions SWIGTCL Defined when using Tcl SWIGXML Defined when using XML

      @@ -144,7 +138,7 @@ In addition, SWIG defines the following set of standard C/C++ macros:
       __LINE__                        Current line number
       __FILE__                        Current file name
      -__STDC__                        Defined to indicate ANSI C
      +__STDC__                        Defined to indicate ISO C
       __cplusplus                     Defined when -c++ option used
       
      @@ -157,7 +151,7 @@ SWIG (except for the symbol `SWIG' which is only defined within the SWIG compiler).

      -

      8.4 Macro Expansion

      +

      10.4 Macro Expansion

      @@ -186,9 +180,9 @@ More complex macros can be defined in the standard way. For example:

       #define EXTERN extern
       #ifdef __STDC__
      -#define _ANSI(args)   (args)
      +#define ISOC_(args)   (args)
       #else
      -#define _ANSI(args) ()
      +#define ISOC_(args) ()
       #endif
       
      @@ -212,7 +206,7 @@ like #x. This is a non-standard SWIG extension.
    -

    8.5 SWIG Macros

    +

    10.5 SWIG Macros

    @@ -222,19 +216,19 @@ For example:

    -%define ARRAYHELPER(type,name)
    +%define ARRAYHELPER(type, name)
     %inline %{
     type *new_ ## name (int nitems) {
    -   return (type *) malloc(sizeof(type)*nitems);
    +  return (type *) malloc(sizeof(type)*nitems);
     }
     void delete_ ## name(type *t) {
    -   free(t);
    +  free(t);
     }
     type name ## _get(type *t, int index) {
    -   return t[index];
    +  return t[index];
     }
     void name ## _set(type *t, int index, type val) {
    -   t[index] = val;
    +  t[index] = val;
     }
     %}
     %enddef
    @@ -258,7 +252,7 @@ many of SWIG's advanced features and libraries are built using this mechanism (s
     support).
     

    -

    8.6 C99 and GNU Extensions

    +

    10.6 C99 and GNU Extensions

    @@ -267,7 +261,7 @@ SWIG-1.3.12 and newer releases support variadic preprocessor macros. For exampl

    -#define DEBUGF(fmt,...)   fprintf(stderr,fmt,__VA_ARGS__)
    +#define DEBUGF(fmt, ...)   fprintf(stderr, fmt, __VA_ARGS__)
     
    @@ -279,12 +273,12 @@ macros defined using %define.

    SWIG allows a variable number of arguments to be empty. However, this often results -in an extra comma (,) and syntax error in the resulting expansion. For example: +in an extra comma (, ) and syntax error in the resulting expansion. For example:

    -DEBUGF("hello");   --> fprintf(stderr,"hello",);
    +DEBUGF("hello");   --> fprintf(stderr, "hello", );
     
    @@ -294,7 +288,7 @@ To get rid of the extra comma, use ## like this:
    -#define DEBUGF(fmt,...)   fprintf(stderr,fmt, ##__VA_ARGS__)
    +#define DEBUGF(fmt, ...)   fprintf(stderr, fmt, ##__VA_ARGS__)
     
    @@ -304,7 +298,7 @@ SWIG also supports GNU-style variadic macros. For example:
    -#define DEBUGF(fmt, args...)  fprintf(stdout,fmt,args)
    +#define DEBUGF(fmt, args...)  fprintf(stdout, fmt, args)
     
    @@ -314,14 +308,14 @@ interface building. However, they are used internally to implement a number of SWIG directives and are provided to make SWIG more compatible with C99 code.

    -

    8.7 Preprocessing and delimiters

    +

    10.7 Preprocessing and delimiters

    The preprocessor handles { }, " " and %{ %} delimiters differently.

    -

    8.7.1 Preprocessing and %{ ... %} & " ... " delimiters

    +

    10.7.1 Preprocessing and %{ ... %} & " ... " delimiters

    @@ -334,7 +328,7 @@ if you write code like this, %{ #ifdef NEED_BLAH int blah() { - ... + ... } #endif %} @@ -346,7 +340,7 @@ the contents of the %{ ... %} block are copied without modification to the output (including all preprocessor directives).

    -

    8.7.2 Preprocessing and { ... } delimiters

    +

    10.7.2 Preprocessing and { ... } delimiters

    @@ -358,11 +352,11 @@ file. For example:

     %extend Foo {
    -   void bar() {
    -      #ifdef DEBUG
    -       printf("I'm in bar\n");
    -      #endif
    -   }
    +  void bar() {
    +    #ifdef DEBUG
    +      printf("I'm in bar\n");
    +    #endif
    +  }
     }
     
    @@ -375,11 +369,11 @@ to actually go into the wrapper file, prefix the preprocessor directives with
     %extend Foo {
    -   void bar() {
    -      %#ifdef DEBUG
    -       printf("I'm in bar\n");
    -      %#endif
    -   }
    +  void bar() {
    +    %#ifdef DEBUG
    +      printf("I'm in bar\n");
    +    %#endif
    +  }
     }
     
    @@ -388,7 +382,7 @@ to actually go into the wrapper file, prefix the preprocessor directives with %
    and leave the preprocessor directive in the code.

    -

    8.8 Preprocessor and Typemaps

    +

    10.8 Preprocessor and Typemaps

    @@ -423,7 +417,7 @@ whereas

     #define SWIG_macro(CAST) (CAST)$input
    -%typemap(in,noblock=1) Int {$1= SWIG_macro(int);}
    +%typemap(in, noblock=1) Int {$1= SWIG_macro(int);}
     
    @@ -459,17 +453,17 @@ would generate -

    8.9 Viewing preprocessor output

    +

    10.9 Viewing preprocessor output

    Like many compilers, SWIG supports a -E command line option to display the output from the preprocessor. -When the -E switch is used, SWIG will not generate any wrappers. +When the -E option is used, SWIG will not generate any wrappers. Instead the results after the preprocessor has run are displayed. This might be useful as an aid to debugging and viewing the results of macro expansions.

    -

    8.10 The #error and #warning directives

    +

    10.10 The #error and #warning directives

    diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index cf0f86024..ee443be53 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -7,7 +7,7 @@ -

    36 SWIG and Python

    +

    32 SWIG and Python

  • A tour of basic C/C++ wrapping
  • Memory management -
  • Python 2.2 and classic classes
  • Cross language polymorphism
  • Tips and techniques
  • Docstring Features @@ -133,6 +139,11 @@
  • Byte string output conversion
  • Python 2 Unicode +
  • Support for Multithreaded Applications + @@ -145,9 +156,9 @@

    This chapter describes SWIG's support of Python. SWIG is compatible -with most recent Python versions including Python 3.0 and Python 2.6, -as well as older versions dating back to Python 2.0. For the best results, -consider using Python 2.3 or newer. +with all recent Python versions (Python 2.7 and Python >= 3.2). If you +still need to generate bindings which work with older versions of Python, +you'll have to use SWIG 3.0.x.

    @@ -157,12 +168,12 @@ very least, make sure you read the "SWIG Basics" chapter.

    -

    36.1 Overview

    +

    32.1 Overview

    To build Python extension modules, SWIG uses a layered approach in which -parts of the extension module are defined in C and other parts are +parts of the extension module are defined in C and other parts are defined in Python. The C layer contains low-level wrappers whereas Python code is used to define high-level features.

    @@ -184,10 +195,10 @@ described followed by a discussion of low-level implementation details.

    -

    36.2 Preliminaries

    +

    32.2 Preliminaries

    -

    36.2.1 Running SWIG

    +

    32.2.1 Running SWIG

    @@ -210,7 +221,7 @@ int fact(int n);

    The #define SWIG_FILE_WITH_INIT line inserts a macro that specifies that the -resulting C file should be built as a python extension, inserting the module +resulting C file should be built as a Python extension, inserting the module init code. This .i file wraps the following simple C file:

    @@ -221,16 +232,15 @@ resulting C file should be built as a python extension, inserting the module #include "example.h" int fact(int n) { - if (n < 0){ /* This should probably return an error, but this is simpler */ - return 0; - } - if (n == 0) { - return 1; - } - else { - /* testing for overflow would be a good idea here */ - return n * fact(n-1); - } + if (n < 0) { /* This should probably return an error, but this is simpler */ + return 0; + } + if (n == 0) { + return 1; + } else { + /* testing for overflow would be a good idea here */ + return n * fact(n-1); + } } @@ -285,13 +295,13 @@ The following sections have further practical examples and details on how you might go about compiling and using the generated files.

    -

    36.2.2 Using distutils

    +

    32.2.2 Using distutils

    -The preferred approach to building an extension module for python is to compile it with -distutils, which comes with all recent versions of python -(Distutils Docs). +The preferred approach to building an extension module for Python is to compile it with +distutils, which comes with all recent versions of Python +(Distutils Docs).

    @@ -300,7 +310,7 @@ flags, headers, etc. for the version of Python it is run with. Distutils will co extension into a shared object file or DLL (.so on Linux, .pyd on Windows, etc). In addition, distutils can handle installing your package into site-packages, if that is desired. A configuration file (conventionally called: setup.py) -describes the extension (and related python modules). The distutils will +describes the extension (and related Python modules). The distutils will then generate all the right compiler directives to build it for you.

    @@ -337,9 +347,9 @@ setup (name = 'example', In this example, the line: example_module = Extension(....) creates an Extension module object, defining the name as _example, and using the source code files: example_wrap.c, generated by swig, and example.c, your original c -source. The swig (and other python extension modules) tradition is for the compiled -extension to have the name of the python portion, prefixed by an underscore. If the name -of your python module is "example.py", then the name of the corresponding object file +source. The swig (and other Python extension modules) tradition is for the compiled +extension to have the name of the Python portion, prefixed by an underscore. If the name +of your Python module is "example.py", then the name of the corresponding object file will be"_example.so"

    @@ -356,11 +366,11 @@ $ python setup.py build_ext --inplace

    And a .so, or .pyd or... will be created for you. It will build a version that matches the -python that you run the command with. Taking apart the command line: +Python that you run the command with. Taking apart the command line:

      -
    • python -- the version of python you want to build for +
    • python -- the version of Python you want to build for
    • setup.py -- the name of your setup script (it can be called anything, but setup.py is the tradition)
    • build_ext -- telling distutils to build extensions @@ -369,7 +379,7 @@ python that you run the command with. Taking apart the command line:

    -The distutils have many other features, consult the python distutils docs for details. +The distutils have many other features, consult the Python distutils docs for details.

    @@ -377,7 +387,7 @@ This same approach works on all platforms if the appropriate compiler is install can even build extensions to the standard Windows Python using MingGW)

    -

    36.2.3 Hand compiling a dynamic module

    +

    32.2.3 Hand compiling a dynamic module

    @@ -395,12 +405,12 @@ $ gcc -shared example.o example_wrap.o -o _example.so

    -The exact commands for doing this vary from platform to platform. -However, SWIG tries to guess the right options when it is installed. Therefore, -you may want to start with one of the examples in the SWIG/Examples/python +The exact commands for doing this vary from platform to platform. +However, SWIG tries to guess the right options when it is installed. Therefore, +you may want to start with one of the examples in the SWIG/Examples/python directory. If that doesn't work, you will need to read the man-pages for your compiler and linker to get the right set of options. You might also -check the SWIG Wiki for +check the SWIG Wiki for additional information.

    @@ -409,7 +419,7 @@ When linking the module, the name of the output file has to match the name of the module prefixed by an underscore. If the name of your module is "example", then the name of the corresponding object file should be "_example.so" or "_examplemodule.so". -The name of the module is specified using the %module directive or the +The name of the module is specified using the %module directive or the -module command line option.

    @@ -425,7 +435,7 @@ module actually consists of two files; socket.py and

    -

    36.2.4 Static linking

    +

    32.2.4 Static linking

    @@ -433,7 +443,7 @@ An alternative approach to dynamic linking is to rebuild the Python interpreter with your extension module added to it. In the past, this approach was sometimes necessary due to limitations in dynamic loading support on certain machines. However, the situation has improved greatly -over the last few years and you should not consider this approach +over the last few years and you should not consider this approach unless there is really no other option.

    @@ -493,7 +503,7 @@ linking if possible. Some programmers may be inclined to use static linking in the interest of getting better performance. However, the performance gained by static linking tends to be rather minimal in most situations (and quite frankly not worth the extra -hassle in the opinion of this author). +hassle in the opinion of this author).

    @@ -504,12 +514,12 @@ If using static linking, you might want to rely on a different approach (perhaps using distutils).

    -

    36.2.5 Using your module

    +

    32.2.5 Using your module

    To use your module, simply use the Python import statement. If -all goes well, you will be able to this: +all goes well, you will be able to run this:

    @@ -552,13 +562,13 @@ Another possible error is the following:
     Traceback (most recent call last):
       File "<stdin>", line 1, in ?
     ImportError: dynamic module does not define init function (init_example)
    ->>>                                                               
    +>>>
     

    -This error is almost always caused when a bad name is given to the shared object file. -For example, if you created a file example.so instead of _example.so you would +This error is almost always caused when a bad name is given to the shared object file. +For example, if you created a file example.so instead of _example.so you would get this error. Alternatively, this error could arise if the name of the module is inconsistent with the module name supplied with the %module directive. Double-check the interface to make sure the module name and the shared object @@ -584,7 +594,7 @@ This error usually indicates that you forgot to include some object files or libraries in the linking of the shared library file. Make sure you compile both the SWIG wrapper file and your original program into a shared library file. Make sure you pass all of the required libraries -to the linker. +to the linker.

    @@ -619,7 +629,7 @@ problem when you try to use your module: Traceback (most recent call last): File "<stdin>", line 1, in ? ImportError: libfoo.so: cannot open shared object file: No such file or directory ->>> +>>> @@ -642,7 +652,7 @@ $ gcc -shared example.o example_wrap.o -L/home/beazley/projects/lib -lfoo \

    Alternatively, you can set the LD_LIBRARY_PATH environment variable to -include the directory with your shared libraries. +include the directory with your shared libraries. If setting LD_LIBRARY_PATH, be aware that setting this variable can introduce a noticeable performance impact on all other applications that you run. To set it only for Python, you might want to do this instead: @@ -661,7 +671,7 @@ system configuration (this requires root access and you will need to read the man pages).

    -

    36.2.6 Compilation of C++ extensions

    +

    32.2.6 Compilation of C++ extensions

    @@ -707,7 +717,7 @@ $ CC -G example.o example_wrap.o -L/opt/SUNWspro/lib -o _example.so -lCrun

    -Of course, the extra libraries to use are completely non-portable---you will +Of course, the extra libraries to use are completely non-portable---you will probably need to do some experimentation.

    @@ -715,8 +725,8 @@ probably need to do some experimentation. Sometimes people have suggested that it is necessary to relink the Python interpreter using the C++ compiler to make C++ extension modules work. In the experience of this author, this has never actually appeared to be -necessary. Relinking the interpreter with C++ really only includes the -special run-time libraries described above---as long as you link your extension +necessary. Relinking the interpreter with C++ really only includes the +special run-time libraries described above---as long as you link your extension modules with these libraries, it should not be necessary to rebuild Python.

    @@ -753,14 +763,14 @@ erratic program behavior. If working with lots of software components, you might want to investigate using a more formal standard such as COM.

    -

    36.2.7 Compiling for 64-bit platforms

    +

    32.2.7 Compiling for 64-bit platforms

    On platforms that support 64-bit applications (Solaris, Irix, etc.), special care is required when building extension modules. On these machines, 64-bit applications are compiled and linked using a different -set of compiler/linker options. In addition, it is not generally possible to mix +set of compiler/linker options. In addition, it is not generally possible to mix 32-bit and 64-bit code together in the same application.

    @@ -786,11 +796,11 @@ careful about the libraries you link with or the library path you use. In general, a Linux distribution will have two set of libraries, one for native x86_64 programs (under /usr/lib64), and another for 32 bits compatibility (under /usr/lib). Also, the compiler options -m32 -and -m64 allow you to choose the desired binary format for your python +and -m64 allow you to choose the desired binary format for your Python extension.

    -

    36.2.8 Building Python Extensions under Windows

    +

    32.2.8 Building Python extensions under Windows

    @@ -802,6 +812,7 @@ are built with Visual Studio 2003), the standard python setup.py build should just work.

    +

    As of python2.5, the distutils support building extensions with MingGW out of the box. Following the instruction here: @@ -814,10 +825,10 @@ If you need to build it on your own, the following notes are provided:

    -You will need to create a DLL that can be loaded into the interpreter. +You will need to create a DLL that can be loaded into the interpreter. This section briefly describes the use of SWIG with Microsoft Visual C++. As a starting point, many of SWIG's examples include project -files (.dsp files) for Visual C++ 6. These can be opened by more +files (.dsp files) for Visual C++ 6. These can be opened by more recent versions of Visual Studio. You might want to take a quick look at these examples in addition to reading this section. @@ -852,12 +863,12 @@ settings, select the "Custom Build" option. "C++:Preprocessor". Add the include directories for your Python installation under "Additional include directories". -

  • Define the symbol __WIN32__ under preprocessor options. +
  • Define the symbol __WIN32__ under preprocessor options.
  • Finally, select the settings for the entire project and go to "Link Options". Add the Python library file to your link libraries. -For example "python21.lib". Also, set the name of the output file to -match the name of your Python module, ie. _example.pyd - Note that _example.dll also worked with Python-2.4 and earlier. +For example "python27.lib". Also, set the name of the output file to +match the name of your Python module, i.e. _example.pyd
  • Build your project. @@ -866,7 +877,7 @@ match the name of your Python module, ie. _example.pyd - Note that _example.dll If all went well, SWIG will be automatically invoked whenever you build your project. Any changes made to the interface file will result in SWIG being automatically executed to produce a new version of -the wrapper file. +the wrapper file.

    @@ -885,9 +896,9 @@ $ python

    If you get an ImportError exception when importing the module, you may have forgotten to include additional library files when you built your module. -If you get an access violation or some kind of general protection fault -immediately upon import, you have a more serious problem. This -is often caused by linking your extension module against the wrong +If you get an access violation or some kind of general protection fault +immediately upon import, you have a more serious problem. This +is often caused by linking your extension module against the wrong set of Win32 debug or thread libraries. You will have to fiddle around with the build options of project to try and track this down.

    @@ -914,12 +925,56 @@ only used by the Visual Studio compiler: Some users have reported success in building extension modules using Cygwin and other compilers. However, the problem of building usable DLLs with these compilers tends to be rather problematic. For the latest information, -you may want to consult the +you may want to consult the SWIG Wiki.

    -

    36.3 A tour of basic C/C++ wrapping

    +

    32.2.9 Additional Python commandline options

    + + +

    +The following table lists the additional commandline options available for the Python module. They can also be seen by using: +

    + +
    +swig -python -help
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Python specific options
    -builtin Create Python built-in types rather than proxy classes, for better performance
    -castmode Enable the casting mode, which allows implicit cast between types in Python
    -debug-doxygen-parser Display doxygen parser module debugging information
    -debug-doxygen-translator Display doxygen translator module debugging information
    -dirvtable Generate a pseudo virtual table for directors for faster dispatch
    -doxygen Convert C++ doxygen comments to pydoc comments in proxy classes
    -extranative Return extra native wrappers for C++ std containers wherever possible
    -fastproxy Use fast proxy mechanism for member methods
    -globals <name> Set <name> used to access C global variable (default: 'cvar')
    -interface <mod>Set low-level C/C++ module name to <mod> (default: module name prefixed by '_')
    -keyword Use keyword arguments
    -nofastunpack Use traditional UnpackTuple method to parse the argument functions
    -noh Don't generate the output header file
    -noproxy Don't generate proxy classes
    -nortti Disable the use of the native C++ RTTI with directors
    -nothreads Disable thread support for the entire interface
    -olddefs Keep the old method definitions when using -fastproxy
    -py3 Generate code with Python 3 specific features and syntax
    -relativeimport Use relative Python imports
    -threads Add thread support for all the interface
    -O Enable the following optimization options: -fastdispatch -fastproxy -fvirtual
    + +

    +Many of these options are covered later on and their use should become clearer by the time you have finished reading this section on SWIG and Python. +

    + +

    32.3 A tour of basic C/C++ wrapping

    @@ -928,7 +983,7 @@ to your C/C++ code. Functions are wrapped as functions, classes are wrapped as This section briefly covers the essential aspects of this wrapping.

    -

    36.3.1 Modules

    +

    32.3.1 Modules

    @@ -938,10 +993,10 @@ wrapped into a Python 'example' module. Underneath the covers, this module consists of a Python source file example.py and a low-level extension module _example.so. When choosing a module name, make sure you don't use the same name as a built-in -Python command or standard module name. +Python command or standard module name.

    -

    36.3.2 Functions

    +

    32.3.2 Functions

    @@ -965,7 +1020,7 @@ like you think it does: >>> -

    36.3.3 Global variables

    +

    32.3.3 Global variables

    @@ -991,8 +1046,8 @@ then "a" and "b" are both names for the object containing the value 3.4. Thus, there is only one object containing 3.4 and "a" and "b" are both names that refer to it. This is quite different than C where a variable name refers to a memory location in which -a value is stored (and assignment copies data into that location). -Because of this, there is no direct way to map variable +a value is stored (and assignment copies data into that location). +Because of this, there is no direct way to map variable assignment in C to variable assignment in Python.

    @@ -1038,7 +1093,7 @@ error message. For example: Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: C variable 'density (double )' ->>> +>>>

    @@ -1103,7 +1158,7 @@ that starts with a leading underscore. SWIG does not create cvar if there are no global variables in a module.

    -

    36.3.4 Constants and enums

    +

    32.3.4 Constants and enums

    @@ -1143,7 +1198,7 @@ other object. Unfortunately, there is no easy way for SWIG to generate code that prevents this. You will just have to be careful.

    -

    36.3.5 Pointers

    +

    32.3.5 Pointers

    @@ -1178,7 +1233,7 @@ When wrapped, you will be able to use the functions in a natural way from Python

    If this makes you uneasy, rest assured that there is no deep magic involved. Underneath the covers, pointers to C/C++ objects are -simply represented as opaque values using an especial python container object: +simply represented as opaque values using an especial Python container object:

    @@ -1188,7 +1243,7 @@ simply represented as opaque values using an especial python container object:
     
     

    This pointer value can be freely passed around to different C functions that -expect to receive an object of type FILE *. The only thing you can't do is +expect to receive an object of type FILE *. The only thing you can't do is dereference the pointer from Python. Of course, that isn't much of a concern in this example.

    @@ -1206,7 +1261,7 @@ _c0671108_p_FILE

    Also, if you need to pass the raw pointer value to some external -python library, you can do it by casting the pointer object to an +Python library, you can do it by casting the pointer object to an integer:

    @@ -1262,16 +1317,16 @@ consider writing some helper functions instead. For example: %inline %{ /* C-style cast */ Bar *FooToBar(Foo *f) { - return (Bar *) f; + return (Bar *) f; } /* C++-style cast */ Foo *BarToFoo(Bar *b) { - return dynamic_cast<Foo*>(b); + return dynamic_cast<Foo*>(b); } Foo *IncrFoo(Foo *f, int i) { - return f+i; + return f+i; } %}
    @@ -1284,7 +1339,7 @@ C-style cast may return a bogus result whereas as the C++-style cast will return None if the conversion can't be performed.

    -

    36.3.6 Structures

    +

    32.3.6 Structures

    @@ -1294,7 +1349,7 @@ a very natural interface. For example,

     struct Vector {
    -  double x,y,z;
    +  double x, y, z;
     };
     
     
    @@ -1308,8 +1363,8 @@ is used as follows: >>> v.x = 3.5 >>> v.y = 7.2 >>> print v.x, v.y, v.z -7.8 -4.5 0.0 ->>> +3.5 7.2 0.0 +>>>

    @@ -1355,12 +1410,12 @@ can also be forced to be read-only using the %immutable directive. For

     struct Foo {
    -   ...
    -   %immutable;
    -   int x;        /* Read-only members */
    -   char *name;
    -   %mutable;
    -   ...
    +  ...
    +  %immutable;
    +  int x;        /* Read-only members */
    +  char *name;
    +  %mutable;
    +  ...
     };
     
    @@ -1368,7 +1423,7 @@ struct Foo {

    When char * members of a structure are wrapped, the contents are assumed to be dynamically allocated using malloc or new (depending on whether or not -SWIG is run with the -c++ option). When the structure member is set, the old contents will be +SWIG is run with the -c++ option). When the structure member is set, the old contents will be released and a new value created. If this is not the behavior you want, you will have to use a typemap (described later).

    @@ -1381,7 +1436,7 @@ example, consider this:
     struct Bar {
    -    int  x[16];
    +  int  x[16];
     };
     
    @@ -1395,7 +1450,7 @@ If accessed in Python, you will see behavior like this: >>> b = example.Bar() >>> print b.x _801861a4_p_int ->>> +>>> @@ -1427,11 +1482,11 @@ pointer. For example, suppose you have two structures like this:
     struct Foo {
    -   int a;
    +  int a;
     };
     
     struct Bar {
    -   Foo f;
    +  Foo f;
     };
     
    @@ -1460,7 +1515,7 @@ Foo *x = &b->f; /* Points inside b */

    -Because the pointer points inside the structure, you can modify the contents and +Because the pointer points inside the structure, you can modify the contents and everything works just like you would expect. For example:

    @@ -1468,12 +1523,33 @@ everything works just like you would expect. For example:
     >>> b = Bar()
     >>> b.f.a = 3               # Modify attribute of structure member
    ->>> x = b.f                   
    +>>> x = b.f
     >>> x.a = 3                 # Modifies the same structure
     
    -

    36.3.7 C++ classes

    +

    +Note that there is a limitation with structs within structs that will cause a problem +if the outer struct is not a named variable in Python. The following will cause a segfault: +

    + +
    +
    +Bar().f.a = 3
    +
    +
    + +

    +because the unnamed Python proxy class for Bar() has its reference count +decremented by the Python interpreter after f has been obtained from it and +before f is used to obtain a. +This results in the underlying Bar instance being deleted, which of course also deletes +f inside it. Hence the pointer to f points to deleted +memory and use of it results in a segfault or some sort of other undefined behaviour. +

    + + +

    32.3.7 C++ classes

    @@ -1510,13 +1586,13 @@ you can use it in Python like this:

    -Class data members are accessed in the same manner as C structures. +Class data members are accessed in the same manner as C structures.

    -Static class members present a special problem for Python. Prior to Python-2.2, +Static class members present a special problem for Python. Prior to Python-2.2, Python classes had no support for static methods and no version of Python -supports static member variables in a manner that SWIG can utilize. Therefore, +supports static member variables in a manner that SWIG can utilize. Therefore, SWIG generates wrappers that try to work around some of these issues. To illustrate, suppose you have a class like this:

    @@ -1525,9 +1601,8 @@ suppose you have a class like this:
     class Spam {
     public:
    -   static void foo();
    -   static int bar;
    -
    +  static void foo();
    +  static int bar;
     };
     
    @@ -1562,7 +1637,7 @@ they are accessed through cvar like this: -

    36.3.8 C++ inheritance

    +

    32.3.8 C++ inheritance

    @@ -1590,11 +1665,11 @@ structure. All of the usual Python utility functions work normally:

     >>> b = Bar()
    ->>> instance(b,Foo)
    +>>> instance(b, Foo)
     1
    ->>> issubclass(Bar,Foo)
    +>>> issubclass(Bar, Foo)
     1
    ->>> issubclass(Foo,Bar)
    +>>> issubclass(Foo, Bar)
     0
     
    @@ -1617,7 +1692,7 @@ then the function spam() accepts Foo * or a pointer to any cla It is safe to use multiple inheritance with SWIG.

    -

    36.3.9 Pointers, references, values, and arrays

    +

    32.3.9 Pointers, references, values, and arrays

    @@ -1670,15 +1745,15 @@ const Foo &spam9();

    then all three functions will return a pointer to some Foo object. -Since the third function (spam8) returns a value, newly allocated memory is used -to hold the result and a pointer is returned (Python will release this memory +Since the third function (spam8) returns a value, newly allocated memory is used +to hold the result and a pointer is returned (Python will release this memory when the return value is garbage collected). The fourth case (spam9) -which returns a const reference, in most of the cases will be +which returns a const reference, in most of the cases will be treated as a returning value, and it will follow the same allocation/deallocation process.

    -

    36.3.10 C++ overloaded functions

    +

    32.3.10 C++ overloaded functions

    @@ -1712,9 +1787,9 @@ Similarly, if you have a class like this,

     class Foo {
     public:
    -    Foo();
    -    Foo(const Foo &);
    -    ...
    +  Foo();
    +  Foo(const Foo &);
    +  ...
     };
     
    @@ -1772,7 +1847,7 @@ To fix this, you either need to ignore or rename one of the methods. For exampl
     %rename(spam_short) spam(short);
     ...
    -void spam(int);    
    +void spam(int);
     void spam(short);   // Accessed as spam_short
     
    @@ -1785,7 +1860,7 @@ or
     %ignore spam(short);
     ...
    -void spam(int);    
    +void spam(int);
     void spam(short);   // Ignored
     
    @@ -1798,10 +1873,10 @@ first declaration takes precedence.

    -Please refer to the "SWIG and C++" chapter for more information about overloading. +Please refer to the "SWIG and C++" chapter for more information about overloading.

    -

    36.3.11 C++ operators

    +

    32.3.11 C++ operators

    @@ -1824,7 +1899,7 @@ public: Complex operator-(const Complex &c) const; Complex operator*(const Complex &c) const; Complex operator-() const; - + double re() const { return rpart; } double im() const { return ipart; } }; @@ -1837,8 +1912,8 @@ When wrapped, it works like you expect:

    ->>> c = Complex(3,4)
    ->>> d = Complex(7,8)
    +>>> c = Complex(3, 4)
    +>>> d = Complex(7, 8)
     >>> e = c + d
     >>> e.re()
     10.0
    @@ -1890,7 +1965,15 @@ Also, be aware that certain operators don't map cleanly to Python.  For instance
     overloaded assignment operators don't map to Python semantics and will be ignored.
     

    -

    36.3.12 C++ namespaces

    +

    +Operator overloading is implemented in the pyopers.swg library file. +In particular overloaded operators are marked with the python:maybecall feature, also known as %pythonmaybecall. +This feature forces SWIG to generate code that return an instance of Python's NotImplemented +instead of raising an exception when the comparison fails, that is, on any kind of error. +This follows the guidelines in PEP 207 - Rich Comparisons and NotImplemented Python constant. +

    + +

    32.3.12 C++ namespaces

    @@ -1904,10 +1987,10 @@ submodules or packages. For example, if you have a file like this, %module example namespace foo { - int fact(int n); - struct Vector { - double x,y,z; - }; + int fact(int n); + struct Vector { + double x, y, z; + }; };

    @@ -1939,11 +2022,11 @@ For example: %rename(Bar_spam) Bar::spam; namespace Foo { - int spam(); + int spam(); } namespace Bar { - int spam(); + int spam(); } @@ -1957,7 +2040,7 @@ utilizes thousands of small deeply nested namespaces each with identical symbol names, well, then you get what you deserve.

    -

    36.3.13 C++ templates

    +

    32.3.13 C++ templates

    @@ -1976,16 +2059,16 @@ For example: template<class T1, class T2> struct pair { - typedef T1 first_type; - typedef T2 second_type; - T1 first; - T2 second; - pair(); - pair(const T1&, const T2&); - ~pair(); + typedef T1 first_type; + typedef T2 second_type; + T1 first; + T2 second; + pair(); + pair(const T1&, const T2&); + ~pair(); }; -%template(pairii) pair<int,int>; +%template(pairii) pair<int, int>; @@ -1996,7 +2079,7 @@ In Python:

     >>> import example
    ->>> p = example.pairii(3,4)
    +>>> p = example.pairii(3, 4)
     >>> p.first
     3
     >>> p.second
    @@ -2006,15 +2089,15 @@ In Python:
     
     

    Obviously, there is more to template wrapping than shown in this example. -More details can be found in the SWIG and C++ chapter. +More details can be found in the SWIG and C++ chapter. Some more complicated examples will appear later.

    -

    36.3.14 C++ Smart Pointers

    +

    32.3.14 C++ Smart Pointers

    -

    36.3.14.1 The shared_ptr Smart Pointer

    +

    32.3.14.1 The shared_ptr Smart Pointer

    @@ -2025,7 +2108,7 @@ in the shared_ptr smart pointer -

    36.3.14.2 Generic Smart Pointers

    +

    32.3.14.2 Generic Smart Pointers

    @@ -2037,9 +2120,9 @@ that implements operator->() like this:

     template<class T> class SmartPtr {
    -   ...
    -   T *operator->();
    -   ...
    +  ...
    +  T *operator->();
    +  ...
     }
     
    @@ -2052,8 +2135,8 @@ Then, if you have a class like this,
     class Foo {
     public:
    -     int x;
    -     int bar();
    +  int x;
    +  int bar();
     };
     
    @@ -2109,7 +2192,7 @@ simply use the __deref__() method. For example: -

    36.3.15 C++ reference counted objects

    +

    32.3.15 C++ reference counted objects

    @@ -2118,7 +2201,7 @@ Python examples of memory management using referencing counting.

    -

    36.4 Further details on the Python class interface

    +

    32.4 Further details on the Python class interface

    @@ -2141,7 +2224,7 @@ the -builtin option are in the Built-in section.

    -

    36.4.1 Proxy classes

    +

    32.4.1 Proxy classes

    @@ -2154,9 +2237,9 @@ have a class like this

     class Foo {
     public:
    -     int x;
    -     int spam(int);
    -     ...
    +  int x;
    +  int spam(int);
    +  ...
     
    @@ -2167,19 +2250,19 @@ then SWIG transforms it into a set of low-level procedural wrappers. For example
     Foo *new_Foo() {
    -    return new Foo();
    +  return new Foo();
     }
     void delete_Foo(Foo *f) {
    -    delete f;
    +  delete f;
     }
     int Foo_x_get(Foo *f) {
    -    return f->x;
    +  return f->x;
     }
     void Foo_x_set(Foo *f, int value) {
    -    f->x = value;
    +  f->x = value;
     }
     int Foo_spam(Foo *f, int arg1) {
    -    return f->spam(arg1);
    +  return f->spam(arg1);
     }
     
    @@ -2189,7 +2272,7 @@ These wrappers can be found in the low-level extension module (e.g., _exampl

    -Using these wrappers, SWIG generates a high-level Python proxy class (also known as a shadow class) like this (shown +Using these wrappers, SWIG generates a high-level Python proxy class (also known as a shadow class) like this (shown for Python 2.2):

    @@ -2204,14 +2287,14 @@ class Foo(object): def __del__(self): if self.thisown: _example.delete_Foo(self.this) - def spam(self,arg1): - return _example.Foo_spam(self.this,arg1) + def spam(self, arg1): + return _example.Foo_spam(self.this, arg1) x = property(_example.Foo_x_get, _example.Foo_x_set)

    -This class merely holds a pointer to the underlying C++ object (.this) and dispatches methods and +This class merely holds a pointer to the underlying C++ object (.this) and dispatches methods and member variable access to that object using the low-level accessor functions. From a user's point of view, it makes the class work normally:

    @@ -2230,7 +2313,7 @@ you can attach new Python methods to the class and you can even inherit from it by Python built-in types until Python 2.2).

    -

    36.4.2 Built-in Types

    +

    32.4.2 Built-in Types

    @@ -2240,8 +2323,8 @@ and built-in types, let's take a look at what a wrapped object looks like under both circumstances.

    -

    When proxy classes are used, each wrapped object in python is an instance -of a pure python class. As a reminder, here is what the __init__ method looks +

    When proxy classes are used, each wrapped object in Python is an instance +of a pure Python class. As a reminder, here is what the __init__ method looks like in a proxy class:

    @@ -2255,37 +2338,30 @@ class Foo(object):

    When a Foo instance is created, the call to _example.new_Foo() -creates a new C++ Foo instance; wraps that C++ instance inside an instance of -a python built-in type called SwigPyObject; and stores the SwigPyObject -instance in the 'this' field of the python Foo object. Did you get all that? So, the -python Foo object is composed of three parts:

    +creates a new C++ Foo instance; wraps that C++ instance inside an instance of +a Python built-in type called SwigPyObject; and stores the SwigPyObject +instance in the 'this' field of the Python Foo object. Did you get all that? So, the +Python Foo object is composed of three parts:

      -
    • The python Foo instance, which contains...
    • +
    • The Python Foo instance, which contains...
    • ... an instance of struct SwigPyObject, which contains...
    • ... a C++ Foo instance
    -

    When -builtin is used, the pure python layer is stripped off. Each -wrapped class is turned into a new python built-in type which inherits from +

    When -builtin is used, the pure Python layer is stripped off. Each +wrapped class is turned into a new Python built-in type which inherits from SwigPyObject, and SwigPyObject instances are returned directly -from the wrapped methods. For more information about python built-in extensions, -please refer to the python documentation:

    +from the wrapped methods. For more information about Python built-in extensions, +please refer to the Python documentation:

    -

    http://docs.python.org/extending/newtypes.html

    +

    https://docs.python.org/3/extending/newtypes.html

    -

    36.4.2.1 Limitations

    +

    32.4.2.1 Limitations

    Use of the -builtin option implies a couple of limitations:

      -
    • python version support:

      -
        -
      • Versions 2.5 and up are fully supported
      • -
      • Versions 2.3 and 2.4 are mostly supported; there are problems with director classes and/or sub-classing a wrapped type in python.
      • -
      • Versions older than 2.3 are not supported.
      • -
      -
    • Some legacy syntax is no longer supported; in particular:

      • The functional interface is no longer exposed. For example, you may no longer call Whizzo.new_CrunchyFrog(). Instead, you must use Whizzo.CrunchyFrog().
      • @@ -2293,15 +2369,15 @@ please refer to the python documentation:

        They are instead accessed in the idiomatic way (Dances.FishSlap).
    • -
    • Wrapped types may not be raised as python exceptions. Here's why: the python internals expect that all sub-classes of Exception will have this struct layout:

      +
    • Wrapped types may not be raised as Python exceptions. Here's why: the Python internals expect that all sub-classes of Exception will have this struct layout:

       typedef struct {
      -    PyObject_HEAD
      -    PyObject *dict;
      -    PyObject *args;
      -    PyObject *message;
      +  PyObject_HEAD
      +  PyObject *dict;
      +  PyObject *args;
      +  PyObject *message;
       } PyBaseExceptionObject;
       
      @@ -2311,12 +2387,12 @@ typedef struct {
       typedef struct {
      -    PyObject_HEAD
      -    void *ptr;
      -    swig_type_info *ty;
      -    int own;
      -    PyObject *next;
      -    PyObject *dict;
      +  PyObject_HEAD
      +  void *ptr;
      +  swig_type_info *ty;
      +  int own;
      +  PyObject *next;
      +  PyObject *dict;
       } SwigPyObject;
       
      @@ -2327,18 +2403,18 @@ typedef struct {
       class MyException {
       public:
      -    MyException (const char *msg_);
      -    ~MyException ();
      +  MyException (const char *msg_);
      +  ~MyException ();
       
      -    const char *what () const;
      +  const char *what () const;
       
       private:
      -    char *msg;
      +  char *msg;
       };
       
      -

      ... you can define this python class, which may be raised as an exception:

      +

      ... you can define this Python class, which may be raised as an exception:

      @@ -2353,22 +2429,22 @@ class MyPyException(Exception):
       
    • Reverse binary operators (e.g., __radd__) are not supported.

      To illustrate this point, if you have a wrapped class called MyString, -and you want to use instances of MyString interchangeably with native python +and you want to use instances of MyString interchangeably with native Python strings, you can define an 'operator+ (const char*)' method :

       class MyString {
       public:
      -    MyString (const char *init);
      -    MyString operator+ (const char *other) const;
      -    ...
      +  MyString (const char *init);
      +  MyString operator+ (const char *other) const;
      +  ...
       };
       

      -SWIG will automatically create an operator overload in python that will allow this: +SWIG will automatically create an operator overload in Python that will allow this:

      @@ -2395,7 +2471,7 @@ episode = "Dead " + mystr

      -The above code fails, because the first operand -- a native python string -- +The above code fails, because the first operand -- a native Python string -- doesn't know how to add an instance of MyString to itself.

    • @@ -2431,7 +2507,7 @@ class Derived : public Base {

      The import "A.i" statement is required, because module B depends on module A.

      -

      As long as you obey these requirements, your python code may import the modules in any order :

      +

      As long as you obey these requirements, your Python code may import the modules in any order :

       import B
      @@ -2442,35 +2518,36 @@ assert(issubclass(B.Derived, A.Base))
       
       
    -

    36.4.2.2 Operator overloads and slots -- use them!

    +

    32.4.2.2 Operator overloads and slots -- use them!

    The entire justification for the -builtin option is improved performance. To that end, the best way to squeeze maximum performance out of your wrappers is to use operator overloads. -Named method dispatch is slow in python, even when compared to other scripting languages. -However, python built-in types have a large number of "slots", +Named method dispatch is slow in Python, even when compared to other scripting languages. +However, Python built-in types have a large number of "slots", analogous to C++ operator overloads, which allow you to short-circuit named method dispatch for certain common operations.

    -

    By default, SWIG will translate most C++ arithmetic operator overloads into python +

    By default, SWIG will translate most C++ arithmetic operator overloads into Python slot entries. For example, suppose you have this class:

     class Twit {
     public:
    -    Twit operator+ (const Twit& twit) const;
    +  Twit operator+ (const Twit& twit) const;
     
    -    // Forward to operator+
    -    Twit add (const Twit& twit) const
    -    { return *this + twit; }
    +  // Forward to operator+
    +  Twit add (const Twit& twit) const {
    +    return *this + twit;
    +  }
     };
     
    -

    SWIG will automatically register operator+ as a python slot operator for addition. You may write python code like this:

    +

    SWIG will automatically register operator+ as a Python slot operator for addition. You may write Python code like this:

    @@ -2483,24 +2560,24 @@ percival = nigel.add(emily)
     
    -

    The last two lines of the python code are equivalent, +

    The last two lines of the Python code are equivalent, but the line that uses the '+' operator is much faster.

    In-place operators (e.g., operator+=) and comparison operators -(operator==, operator<, etc.) are also converted to python +(operator==, operator<, etc.) are also converted to Python slot operators. For a complete list of C++ operators that are -automatically converted to python slot operators, refer to the file +automatically converted to Python slot operators, refer to the file python/pyopers.swig in the SWIG library.

    -Read about all of the available python slots here: -http://docs.python.org/c-api/typeobj.html

    +Read about all of the available Python slots here: +https://docs.python.org/3/c-api/typeobj.html

    -There are two ways to define a python slot function: dispatch to a +There are two ways to define a Python slot function: dispatch to a statically defined function; or dispatch to a method defined on the operand.

    @@ -2546,16 +2623,16 @@ public:

    -If you examine the generated code, the supplied hash function will now be +If you examine the generated code, the supplied hash function will now be the function callback in the tp_hash slot for the builtin type for MyClass:

     static PyHeapTypeObject SwigPyBuiltin__MyClass_type = {
    -    ...
    -    (hashfunc) myHashFunc,       /* tp_hash */
    -    ...
    +  ...
    +  (hashfunc) myHashFunc,       /* tp_hash */
    +  ...
     
    @@ -2587,7 +2664,7 @@ class MyClass {

    -NOTE: Some python slots use a method signature which does not +NOTE: Some Python slots use a method signature which does not match the signature of SWIG-wrapped methods. For those slots, SWIG will automatically generate a "closure" function to re-marshal the arguments before dispatching to the wrapped method. Setting @@ -2601,7 +2678,7 @@ in the file python/pyopers.swig in the SWIG library.

    -

    36.4.3 Memory management

    +

    32.4.3 Memory management

    NOTE: Although this section refers to proxy objects, everything here also applies @@ -2610,7 +2687,7 @@ when the -builtin option is used.

    Associated with proxy object, is an ownership flag .thisown The value of this flag determines who is responsible for deleting the underlying C++ object. If set to 1, -the Python interpreter will destroy the C++ object when the proxy class is +the Python interpreter will destroy the C++ object when the proxy class is garbage collected. If set to 0 (or if the attribute is missing), then the destruction of the proxy class has no effect on the C++ object.

    @@ -2624,8 +2701,8 @@ ownership of the result. For example:
     class Foo {
     public:
    -    Foo();
    -    Foo bar();
    +  Foo();
    +  Foo bar();
     };
     
    @@ -2654,9 +2731,9 @@ they came from. Therefore, the ownership is set to zero. For example:
     class Foo {
     public:
    -    ...
    -    Foo *spam();
    -    ...
    +  ...
    +  Foo *spam();
    +  ...
     };
     
    @@ -2695,8 +2772,8 @@ or global variable. For example, consider this interface: %module example struct Foo { - int value; - Foo *next; + int value; + Foo *next; }; Foo *head = 0; @@ -2713,7 +2790,7 @@ is assigned to a global variable. For example: >>> f = example.Foo() >>> f.thisown 1 ->>> example.cvar.head = f +>>> example.cvar.head = f >>> f.thisown 0 >>> @@ -2749,10 +2826,10 @@ change the ownership of an object. For instance, consider code like this:
     class Node {
    -   Object *value;
    +  Object *value;
     public:
    -   void set_value(Object *v) { value = v; }
    -   ...
    +  void set_value(Object *v) { value = v; }
    +  ...
     };
     
    @@ -2796,44 +2873,7 @@ It is also possible to deal with situations like this using typemaps--an advanced topic discussed later.

    -

    36.4.4 Python 2.2 and classic classes

    - - -

    -SWIG makes every attempt to preserve backwards compatibility with -older versions of Python to the extent that it is possible. However, -in Python-2.2, an entirely new type of class system was introduced. -This new-style class system offers many enhancements including static -member functions, properties (managed attributes), and class methods. -Details about all of these changes can be found on www.python.org and is not repeated here. -

    - -

    -To address differences between Python versions, SWIG currently emits -dual-mode proxy class wrappers. In Python-2.2 and newer releases, -these wrappers encapsulate C++ objects in new-style classes that take -advantage of new features (static methods and properties). However, -if these very same wrappers are imported into an older version of Python, -old-style classes are used instead. -

    - -

    -This dual-nature of the wrapper code means that you can create extension -modules with SWIG and those modules will work with all versions of Python -ranging from Python-2.0 to the very latest release. Moreover, the wrappers take -advantage of Python-2.2 features when available. -

    - -

    -For the most part, the interface presented to users is the same regardless -of what version of Python is used. The only incompatibility lies in the handling -of static member functions. In Python-2.2, they can be accessed via the -class itself. In Python-2.1 and earlier, they have to be accessed as a global -function or through an instance (see the earlier section). -

    - -

    36.5 Cross language polymorphism

    +

    32.5 Cross language polymorphism

    @@ -2867,7 +2907,7 @@ proxy classes, director classes, and C wrapper functions takes care of all the cross-language method routing transparently.

    -

    36.5.1 Enabling directors

    +

    32.5.1 Enabling directors

    @@ -2884,18 +2924,18 @@ option to the %module directive, like this:

    Without this option no director code will be generated. Second, you -must use the %feature("director") directive to tell SWIG which classes -and methods should get directors. The %feature directive can be applied +must use the %feature("director") directive to tell SWIG which classes +and methods should get directors. The %feature directive can be applied globally, to specific classes, and to specific methods, like this:

     // generate directors for all classes that have virtual methods
    -%feature("director");         
    +%feature("director");
     
    -// generate directors for all virtual methods in class Foo
    -%feature("director") Foo;      
    +// generate directors for the virtual methods in class Foo
    +%feature("director") Foo;
     
    @@ -2912,12 +2952,12 @@ directors for specific classes or methods. So for example,

    -will generate directors for all virtual methods of class Foo except -bar(). +will generate directors for the virtual methods of class Foo except +bar().

    -Directors can also be generated implicitly through inheritance. +Directors can also be generated implicitly through inheritance. In the following, class Bar will get a director class that handles the methods one() and two() (but not three()):

    @@ -2927,21 +2967,21 @@ the methods one() and two() (but not three()): %feature("director") Foo; class Foo { public: - Foo(int foo); - virtual ~Foo(); - virtual void one(); - virtual void two(); + Foo(int foo); + virtual ~Foo(); + virtual void one(); + virtual void two(); }; class Bar: public Foo { public: - virtual void three(); + virtual void three(); };

    -then at the python side you can define +then at the Python side you can define

    @@ -2954,15 +2994,12 @@ class MyFoo(mymodule.Foo): # super().__init__(foo) # Alternative construction for Python3 def one(self): - print "one from python" + print "one from Python"
    -

    36.5.2 Director classes

    - - - +

    32.5.2 Director classes

    @@ -2981,7 +3018,8 @@ For simplicity let's ignore the Swig::Director class and refer to the original C++ class as the director's base class. By default, a director class extends all virtual methods in the inheritance chain of its base class (see the preceding section for how to modify this behavior). -Thus all virtual method calls, whether they originate in C++ or in +Virtual methods that have a final specifier are unsurprisingly excluded. +Thus the virtual method calls, whether they originate in C++ or in Python via proxy classes, eventually end up in at the implementation in the director class. The job of the director methods is to route these method calls to the appropriate place in the inheritance chain. By @@ -3041,7 +3079,7 @@ so there is no need for the extra overhead involved with routing the calls through Python.

    -

    36.5.3 Ownership and object destruction

    +

    32.5.3 Ownership and object destruction

    @@ -3078,12 +3116,12 @@ references. Here is an example:

     class Foo {
     public:
    -    ...
    +  ...
     };
     class FooContainer {
     public:
    -    void addFoo(Foo *);
    -    ...
    +  void addFoo(Foo *);
    +  ...
     };
     
    @@ -3108,7 +3146,7 @@ deleting all the Foo pointers it contains at some point. Note that no hard references to the Foo objects remain in Python.

    -

    36.5.4 Exception unrolling

    +

    32.5.4 Exception unrolling

    @@ -3124,9 +3162,9 @@ suffice in most cases:

     %feature("director:except") {
    -    if ($error != NULL) {
    -        throw Swig::DirectorMethodException();
    -    }
    +  if ($error != NULL) {
    +    throw Swig::DirectorMethodException();
    +  }
     }
     
    @@ -3153,8 +3191,8 @@ suitable exception handler:
     %exception {
    -    try { $action }
    -    catch (Swig::DirectorException &e) { SWIG_fail; }
    +  try { $action }
    +  catch (Swig::DirectorException &e) { SWIG_fail; }
     }
     
    @@ -3167,7 +3205,7 @@ Swig::DirectorMethodException is thrown, Python will register the exception as soon as the C wrapper function returns.

    -

    36.5.5 Overhead and code bloat

    +

    32.5.5 Overhead and code bloat

    @@ -3201,7 +3239,7 @@ directive) for only those methods that are likely to be extended in Python.

    -

    36.5.6 Typemaps

    +

    32.5.6 Typemaps

    @@ -3215,7 +3253,7 @@ need to be supported.

    -

    36.5.7 Miscellaneous

    +

    32.5.7 Miscellaneous

    @@ -3225,13 +3263,13 @@ be able to use std::vector, std::string, etc., as you would any other type.

    Note: The director typemaps for return types based in const -references, such as +references, such as

     class Foo {
     …
    -    virtual const int& bar();
    +  virtual const int& bar();
     …
     };
     
    @@ -3249,7 +3287,7 @@ types, wherever possible, for example
     class Foo {
     …
    -    virtual int bar();
    +  virtual int bar();
     …
     };
     
    @@ -3262,7 +3300,7 @@ methods that return const references.

    -

    36.6 Common customization features

    +

    32.6 Common customization features

    @@ -3275,7 +3313,7 @@ This section describes some common SWIG features that are used to improve your the interface to an extension module.

    -

    36.6.1 C/C++ helper functions

    +

    32.6.1 C/C++ helper functions

    @@ -3297,11 +3335,11 @@ For example, you might get errors like this:

     >>> a = [
    -...   [1,0,0,0],
    -...   [0,1,0,0],
    -...   [0,0,1,0],
    -...   [0,0,0,1]]
    ->>> set_transform(im,a)
    +...   [1, 0, 0, 0],
    +...   [0, 1, 0, 0],
    +...   [0, 0, 1, 0],
    +...   [0, 0, 0, 1]]
    +>>> set_transform(im, a)
     Traceback (most recent call last):
       File "<stdin>", line 1, in ?
     TypeError: Type error. Expected _p_a_4__double
    @@ -3319,16 +3357,16 @@ functions.  Just use the %inline directive. For example:
     %inline %{
     /* Note: double[4][4] is equivalent to a pointer to an array double (*)[4] */
     double (*new_mat44())[4] {
    -   return (double (*)[4]) malloc(16*sizeof(double));
    +  return (double (*)[4]) malloc(16*sizeof(double));
     }
     void free_mat44(double (*x)[4]) {
    -   free(x);
    +  free(x);
     }
     void mat44_set(double x[4][4], int i, int j, double v) {
    -   x[i][j] = v;
    +  x[i][j] = v;
     }
     double mat44_get(double x[4][4], int i, int j) {
    -   return x[i][j];
    +  return x[i][j];
     }
     %}
     
    @@ -3341,11 +3379,11 @@ From Python, you could then write code like this:
     >>> a = new_mat44()
    ->>> mat44_set(a,0,0,1.0)
    ->>> mat44_set(a,1,1,1.0)
    ->>> mat44_set(a,2,2,1.0)
    +>>> mat44_set(a, 0, 0, 1.0)
    +>>> mat44_set(a, 1, 1, 1.0)
    +>>> mat44_set(a, 2, 2, 1.0)
     ...
    ->>> set_transform(im,a)
    +>>> set_transform(im, a)
     >>>
     
    @@ -3356,7 +3394,7 @@ hard to implement. It is possible to clean this up using Python code, typemaps, customization features as covered in later sections.

    -

    36.6.2 Adding additional Python code

    +

    32.6.2 Adding additional Python code

    @@ -3373,13 +3411,13 @@ void set_transform(Image *im, double x[4][4]); ... /* Rewrite the high level interface to set_transform */ %pythoncode %{ -def set_transform(im,x): - a = new_mat44() - for i in range(4): - for j in range(4): - mat44_set(a,i,j,x[i][j]) - _example.set_transform(im,a) - free_mat44(a) +def set_transform(im, x): + a = new_mat44() + for i in range(4): + for j in range(4): + mat44_set(a, i, j, x[i][j]) + _example.set_transform(im, a) + free_mat44(a) %}

    @@ -3392,11 +3430,11 @@ low-level helper functions. For example, this code now seems to work:
     >>> a = [
    -...   [1,0,0,0],
    -...   [0,1,0,0],
    -...   [0,0,1,0],
    -...   [0,0,0,1]]
    ->>> set_transform(im,a)
    +...   [1, 0, 0, 0],
    +...   [0, 1, 0, 0],
    +...   [0, 0, 1, 0],
    +...   [0, 0, 0, 1]]
    +>>> set_transform(im, a)
     >>>
     
    @@ -3421,7 +3459,9 @@ statements.

    -The following shows example usage for Python 2.6 to use print as it can in Python 3, that is, as a function instead of a statement: +The following example for Python 2.x shows how to insert code into the +generated wrapper to enable print to be used as a Python3-compatible +function instead of a statement:

    @@ -3438,13 +3478,13 @@ print("Loading", "Whizz", "Bang", sep=' ... ')

    -which can be seen when viewing the first few lines of the generated .py file: +The insert code can be seen at the start of the generated .py file:

     # This file was automatically generated by SWIG (http://www.swig.org).
    -# Version 2.0.11
    +# Version 4.0.0
     #
     # Do not make changes to this file unless you know what you are doing--modify
     # the SWIG interface file instead.
    @@ -3470,7 +3510,7 @@ an error for invalid preprocessor directives, so you may have to update
     existing interface files to delimit blocks of Python code correctly.

    As an alternative to providing a block containing Python code, you can -include python code from a file. The code is inserted exactly as in the +include Python code from a file. The code is inserted exactly as in the file, so this avoids any issues with the SWIG preprocessor. It's a good approach if you have a non-trivial chunk of Python code to insert. To use this feature you specify a filename in double quotes, for example:

    @@ -3491,7 +3531,7 @@ entirely replace a proxy function you can use
     %module example
     
    -// Rewrite bar() python code
    +// Rewrite bar() Python code
     
     %feature("shadow") Foo::bar(int) %{
     def bar(*args):
    @@ -3499,16 +3539,16 @@ def bar(*args):
         $action
         #do something after
     %}
    -    
    +
     class Foo {
     public:
    -    int bar(int x);
    +  int bar(int x);
     };
     

    where $action will be replaced by the call to -the C/C++ proper method. +the C/C++ proper method.

    @@ -3526,20 +3566,21 @@ proxy, just before the return statement.

     %module example
     
    -// Add python code to bar() 
    +// Add Python code to bar()
     
     %feature("pythonprepend") Foo::bar(int) %{
    -   #do something before C++ call
    +    #do something before C++ call
     %}
     
     %feature("pythonappend") Foo::bar(int) %{
    -   #do something after C++ call
    +    #do something after C++ call
    +    #the 'val' variable holds the return value
     %}
     
    -    
    +
     class Foo {
     public:
    -    int bar(int x);
    +  int bar(int x);
     };
     
    @@ -3555,20 +3596,21 @@ SWIG version 1.3.28 you can use the directive forms
     %module example
     
    -// Add python code to bar() 
    +// Add Python code to bar()
     
     %pythonprepend Foo::bar(int) %{
    -   #do something before C++ call
    +    #do something before C++ call
     %}
     
     %pythonappend Foo::bar(int) %{
    -   #do something after C++ call
    +    #do something after C++ call
    +    #the 'val' variable holds the return value
     %}
     
    -    
    +
     class Foo {
     public:
    -    int bar(int x);
    +  int bar(int x);
     };
     
    @@ -3584,21 +3626,21 @@ as it will then get attached to all the overloaded C++ methods. For example:
     %module example
     
    -// Add python code to bar()
    +// Add Python code to bar()
     
     %pythonprepend Foo::bar %{
    -   #do something before C++ call
    +    #do something before C++ call
     %}
     
     %pythonappend Foo::bar %{
    -   #do something after C++ call
    +    #do something after C++ call
     %}
     
     
     class Foo {
     public:
    -    int bar(int x);
    -    int bar();
    +  int bar(int x);
    +  int bar();
     };
     
    @@ -3608,7 +3650,7 @@ The same applies for overloaded constructors.

    -

    36.6.3 Class extension with %extend

    +

    32.6.3 Class extension with %extend

    @@ -3625,22 +3667,22 @@ Here is a simple example: %} struct Vector { - double x,y,z; + double x, y, z; }; %extend Vector { - char *__str__() { - static char tmp[1024]; - sprintf(tmp,"Vector(%g,%g,%g)", $self->x,$self->y,$self->z); - return tmp; - } - Vector(double x, double y, double z) { - Vector *v = (Vector *) malloc(sizeof(Vector)); - v->x = x; - v->y = y; - v->z = z; - return v; - } + char *__str__() { + static char tmp[1024]; + sprintf(tmp, "Vector(%g, %g, %g)", $self->x, $self->y, $self->z); + return tmp; + } + Vector(double x, double y, double z) { + Vector *v = (Vector *) malloc(sizeof(Vector)); + v->x = x; + v->y = y; + v->z = z; + return v; + } }; @@ -3651,28 +3693,28 @@ Now, in Python

    ->>> v = example.Vector(2,3,4)
    +>>> v = example.Vector(2, 3, 4)
     >>> print v
    -Vector(2,3,4)
    +Vector(2, 3, 4)
     >>>
     

    -%extend can be used for many more tasks than this. +%extend can be used for many more tasks than this. For example, if you wanted to overload a Python operator, you might do this:

     %extend Vector {
    -    Vector __add__(Vector *other) {
    -         Vector v;
    -         v.x = $self->x + other->x;
    -         v.y = $self->y + other->y;
    -         v.z = $self->z + other->z;
    -         return v;
    -    }
    +  Vector __add__(Vector *other) {
    +    Vector v;
    +    v.x = $self->x + other->x;
    +    v.y = $self->y + other->y;
    +    v.z = $self->z + other->z;
    +    return v;
    +  }
     };
     
    @@ -3684,11 +3726,11 @@ Use it like this:
     >>> import example
    ->>> v = example.Vector(2,3,4)
    ->>> w = example.Vector(10,11,12)
    +>>> v = example.Vector(2, 3, 4)
    +>>> w = example.Vector(10, 11, 12)
     >>> print v+w
    -Vector(12,14,16)
    ->>> 
    +Vector(12, 14, 16)
    +>>>
     
    @@ -3697,7 +3739,7 @@ Vector(12,14,16) in any way---the extensions only show up in the Python interface.

    -

    36.6.4 Exception handling with %exception

    +

    32.6.4 Exception handling with %exception

    @@ -3716,8 +3758,8 @@ or a NULL pointer perhaps). Here is a simple example of how you might handle th %exception malloc { $action if (!result) { - PyErr_SetString(PyExc_MemoryError,"Not enough memory"); - return NULL; + PyErr_SetString(PyExc_MemoryError, "Not enough memory"); + SWIG_fail; } } void *malloc(size_t nbytes); @@ -3746,11 +3788,11 @@ that. For example:

     %exception {
    -   $action
    -   if (err_occurred()) {
    -      PyErr_SetString(PyExc_RuntimeError, err_message());
    -      return NULL;
    -   }
    +  $action
    +  if (err_occurred()) {
    +    PyErr_SetString(PyExc_RuntimeError, err_message());
    +    SWIG_fail;
    +  }
     }
     
    @@ -3766,25 +3808,26 @@ C++ exceptions are also easy to handle. For example, you can write code like th
     %exception getitem {
    -   try {
    -      $action
    -   } catch (std::out_of_range &e) {
    -      PyErr_SetString(PyExc_IndexError, const_cast<char*>(e.what()));
    -      return NULL;
    -   }
    +  try {
    +    $action
    +  } catch (std::out_of_range &e) {
    +    PyErr_SetString(PyExc_IndexError, const_cast<char*>(e.what()));
    +    SWIG_fail;
    +  }
     }
     
     class Base {
     public:
    -     Foo *getitem(int index);      // Exception handled added
    -     ...
    +  Foo *getitem(int index);      // Exception handled added
    +  ...
     };
     

    When raising a Python exception from C, use the PyErr_SetString() -function as shown above. The following exception types can be used as the first argument. +function as shown above followed by SWIG_fail. +The following exception types can be used as the first argument.

    @@ -3818,12 +3861,155 @@ PyExc_ZeroDivisionError
    +

    +SWIG_fail is a C macro which when called within the context of SWIG wrapper function, +will jump to the error handler code. This will call any cleanup code (freeing any temp variables) +and then return from the wrapper function so that the Python interpreter can raise the Python exception. +This macro should always be called after setting a Python error in code snippets, such as typemaps and %exception, that are ultimately generated into the wrapper function. +

    +

    The language-independent exception.i library file can also be used to raise exceptions. See the SWIG Library chapter.

    -

    36.7 Tips and techniques

    +

    32.6.5 Optimization options

    + + +

    32.6.5.1 -fastproxy

    + + +

    +The -fastproxy command line option enables faster method calling as the call is made directly into the C/C++ layer rather than going through a method wrapper. +

    + +

    +Consider wrapping a C++ class: +

    + +
    +
    +struct Go {
    +  void callme0() {}
    +  void callme4(int a, int b, int c, int d) {}
    +  void callme8(double a, double b, double c, double d, double e, double f, double g, double i) {}
    +};
    +
    +
    + +

    +The default generated proxy class is: +

    + +
    +
    +class Go(object):
    +    def callme0(self):
    +        return _example.Go_callme0(self)
    +
    +    def callme4(self, a, b, c, d):
    +        return _example.Go_callme4(self, a, b, c, d)
    +
    +    def callme8(self, a, b, c, d, e, f, g, i):
    +        return _example.Go_callme8(self, a, b, c, d, e, f, g, i)
    +    ...
    +
    +
    + +

    +Each method in the Python class contains a Python proxy method which passes the arguments on to the underlying function in the low-level C/C++ module (_example in this case). +The generated proxy class when using -fastproxy is: +

    + +
    +
    +%module example
    +class Go(object):
    +    callme0 = _swig_new_instance_method(_example.Go_callme0)
    +    callme4 = _swig_new_instance_method(_example.Go_callme4)
    +    callme8 = _swig_new_instance_method(_example.Go_callme8)
    +    ...
    +
    +
    + +

    +where _swig_new_instance_method adds the method to the proxy class via C API calls for direct access to the underlying function in the low-level C/C++ module. +Note that for some methods it is not possible to generate the direct access call and so -fastproxy is ignored. +This happens, for example, when adding additional code to Python proxy methods, such as using %pythonprepend. +

    + +

    +The overhead calling into C/C++ from Python is reduced slightly using -fastproxy. +Below are some timings in microseconds calling the 3 functions in the example above. +Also included in the table for comparison is using the -builtin option covered in the +Built-in Types. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Method nameDefault-fastproxy-builtin
    callme00.150.090.07
    callme40.260.160.14
    callme80.320.200.17
    + +

    +Although the -fastproxy option results in faster code over the default, the generated proxy code is not as user-friendly +as docstring/doxygen comments and functions with default values are not visible in the generated Python proxy class. +The -olddefs option can rectify this. +

    + +

    +The generated proxy class for the example above when using -fastproxy -olddefs is: +

    + +
    +
    +class Go(object):
    +    def callme0(self):
    +        return _example.Go_callme0(self)
    +    callme0 = _swig_new_instance_method(_example.Go_callme0)
    +
    +    def callme4(self, a, b, c, d):
    +        return _example.Go_callme4(self, a, b, c, d)
    +    callme4 = _swig_new_instance_method(_example.Go_callme4)
    +
    +    def callme8(self, a, b, c, d, e, f, g, i):
    +        return _example.Go_callme8(self, a, b, c, d, e, f, g, i)
    +    callme8 = _swig_new_instance_method(_example.Go_callme8)
    +    ...
    +
    +
    + +

    +The class defines each method in two different ways. The first definition is replaced by the second definition and so the second definition is the one used when the method is called. +While this possibly provides the best of both worlds, the time to import the module will be slightly slower when the class is defined due to the additional method definitions. +

    + +

    +The command line options mentioned above also apply to wrapped C/C++ global functions, not just class methods. +

    + +

    32.7 Tips and techniques

    @@ -3833,7 +4019,7 @@ strings, binary data, and arrays. This chapter discusses the common techniques solving these problems.

    -

    36.7.1 Input and output parameters

    +

    32.7.1 Input and output parameters

    @@ -3844,7 +4030,7 @@ example:

     void add(int x, int y, int *result) {
    -   *result = x + y;
    +  *result = x + y;
     }
     
    @@ -3856,7 +4042,7 @@ or perhaps
     int sub(int *x, int *y) {
    -   return *x-*y;
    +  return *x-*y;
     }
     
    @@ -3881,10 +4067,10 @@ In Python, this allows you to pass simple values. For example:
    ->>> a = add(3,4)
    +>>> a = add(3, 4)
     >>> print a
     7
    ->>> b = sub(7,4)
    +>>> b = sub(7, 4)
     >>> print b
     3
     >>>
    @@ -3921,7 +4107,7 @@ If a function mutates one of its parameters like this,
     
     void negate(int *x) {
    -   *x = -(*x);
    +  *x = -(*x);
     }
     
    @@ -3984,7 +4170,7 @@ int send_message(char *text, int *success);

    -When used in Python, the function will return multiple values. +When used in Python, the function will return multiple values.

    @@ -4027,7 +4213,7 @@ Now, in Python:
    ->>> r,c = get_dimensions(m)
    +>>> r, c = get_dimensions(m)
     
    @@ -4046,7 +4232,7 @@ void foo(Bar *OUTPUT); may not have the intended effect since typemaps.i does not define an OUTPUT rule for Bar.

    -

    36.7.2 Simple pointers

    +

    32.7.2 Simple pointers

    @@ -4068,7 +4254,7 @@ extern void add(int x, int y, int *result);

    -The %pointer_functions(type,name) macro generates five helper functions that can be used to create, +The %pointer_functions(type, name) macro generates five helper functions that can be used to create, destroy, copy, assign, and dereference a pointer. In this case, the functions are as follows:

    @@ -4091,7 +4277,7 @@ In Python, you would use the functions like this: >>> result = new_intp() >>> print result _108fea8_p_int ->>> add(3,4,result) +>>> add(3, 4, result) >>> print intp_value(result) 7 >>> @@ -4099,13 +4285,13 @@ _108fea8_p_int

    -If you replace %pointer_functions() by %pointer_class(type,name), the interface is more class-like. +If you replace %pointer_functions() by %pointer_class(type, name), the interface is more class-like.

     >>> result = intp()
    ->>> add(3,4,result)
    +>>> add(3, 4, result)
     >>> print result.value()
     7
     
    @@ -4115,7 +4301,7 @@ If you replace %pointer_functions() by %pointer_class(type,name)SWIG Library chapter for further details.

    -

    36.7.3 Unbounded C Arrays

    +

    32.7.3 Unbounded C Arrays

    @@ -4125,17 +4311,17 @@ Sometimes a C function expects an array to be passed as a pointer. For example,

     int sumitems(int *first, int nitems) {
    -    int i, sum = 0;
    -    for (i = 0; i < nitems; i++) {
    -        sum += first[i];
    -    }
    -    return sum;
    +  int i, sum = 0;
    +  for (i = 0; i < nitems; i++) {
    +    sum += first[i];
    +  }
    +  return sum;
     }
     

    -To wrap this into Python, you need to pass an array pointer as the first argument. +To wrap this into Python, you need to pass an array pointer as the first argument. A simple way to do this is to use the carrays.i library file. For example:

    @@ -4157,7 +4343,7 @@ For instance, you will be able to do this in Python: >>> a = intArray(10000000) # Array of 10-million integers >>> for i in xrange(10000): # Set some values ... a[i] = i ->>> sumitems(a,10000) +>>> sumitems(a, 10000) 49995000 >>> @@ -4177,7 +4363,7 @@ well suited for applications in which you need to create buffers, package binary data, etc.

    -

    36.7.4 String handling

    +

    32.7.4 String handling

    @@ -4212,13 +4398,13 @@ using the cstring.i library file described in the 36.7.5 Default arguments +

    32.7.5 Default arguments

    C++ default argument code generation is documented in the main Default arguments section. -There is also an optional Python specific feature that can be used called the python:cdefaultargs +There is also an optional Python specific feature that can be used called the python:cdefaultargs feature flag. By default, SWIG attempts to convert C++ default argument values into Python values and generates code into the Python layer containing these values. @@ -4296,7 +4482,7 @@ class CDA(object):

    Adding the feature:

    - +
     %feature("python:cdefaultargs") CDA::fff;
    @@ -4346,7 +4532,7 @@ Versions of SWIG prior to this varied in their ability to convert C++ default va
     equivalent Python default argument values.
     

    -

    36.8 Typemaps

    +

    32.8 Typemaps

    @@ -4357,17 +4543,17 @@ as the material in the "Typemaps" chapter.

    -Before proceeding, it should be stressed that typemaps are not a required +Before proceeding, it should be stressed that typemaps are not a required part of using SWIG---the default wrapping behavior is enough in most cases. Typemaps are only used if you want to change some aspect of the primitive C-Python interface or if you want to elevate your guru status.

    -

    36.8.1 What is a typemap?

    +

    32.8.1 What is a typemap?

    -A typemap is nothing more than a code generation rule that is attached to +A typemap is nothing more than a code generation rule that is attached to a specific C datatype. For example, to convert integers from Python to C, you might define a typemap like this:

    @@ -4377,7 +4563,7 @@ you might define a typemap like this: %typemap(in) int { $1 = (int) PyLong_AsLong($input); - printf("Received an integer : %d\n",$1); + printf("Received an integer : %d\n", $1); } %inline %{ extern int fact(int n); @@ -4416,8 +4602,8 @@ You can refine this by supplying an optional parameter name. For example: %typemap(in) int nonnegative { $1 = (int) PyLong_AsLong($input); if ($1 < 0) { - PyErr_SetString(PyExc_ValueError,"Expected a nonnegative value."); - return NULL; + PyErr_SetString(PyExc_ValueError, "Expected a nonnegative value."); + SWIG_fail; } } %inline %{ @@ -4441,7 +4627,7 @@ the typemap system follows typedef declarations. For example:
     %typemap(in) int n {
       $1 = (int) PyLong_AsLong($input);
    -  printf("n = %d\n",$1);
    +  printf("n = %d\n", $1);
     }
     %inline %{
     typedef int Integer;
    @@ -4457,8 +4643,8 @@ Typemaps can also be defined for groups of consecutive arguments.  For example:
     
     %typemap(in) (char *str, int len) {
    -    $1 = PyString_AsString($input);
    -    $2 = PyString_Size($input);
    +  $1 = PyString_AsString($input);
    +  $2 = PyString_Size($input);
     };
     
     int count(char c, char *str, int len);
    @@ -4473,13 +4659,13 @@ parameter is omitted):
     
     
    ->>> example.count('e','Hello World')
    +>>> example.count('e', 'Hello World')
     1
     >>>
     
    -

    36.8.2 Python typemaps

    +

    32.8.2 Python typemaps

    @@ -4499,7 +4685,7 @@ like this:

    A detailed list of available methods can be found in the "Typemaps" chapter. +href="Typemaps.html#Typemaps">Typemaps" chapter.

    @@ -4510,7 +4696,7 @@ looking at the files in the SWIG library. Just take into account that in the latest versions of swig (1.3.22+), the library files are not very pristine clear for the casual reader, as they used to be. The extensive use of macros and other ugly techniques in the latest -version produce a very powerful and consistent python typemap library, +version produce a very powerful and consistent Python typemap library, but at the cost of simplicity and pedagogic value.

    @@ -4520,7 +4706,7 @@ a look at the SWIG library version 1.3.20 or so.

    -

    36.8.3 Typemap variables

    +

    32.8.3 Typemap variables

    @@ -4561,7 +4747,7 @@ A PyObject * that holds the result to be returned to Python.

    -The parameter name that was matched. +The parameter name that was matched.

    @@ -4591,7 +4777,7 @@ properly assigned. The Python name of the wrapper function being created.

    -

    36.8.4 Useful Python Functions

    +

    32.8.4 Useful Python Functions

    @@ -4719,7 +4905,7 @@ write me

    -

    36.9 Typemap Examples

    +

    32.9 Typemap Examples

    @@ -4728,7 +4914,7 @@ might look at the files "python.swg" and "typemaps.i" in the SWIG library.

    -

    36.9.1 Converting Python list to a char **

    +

    32.9.1 Converting Python list to a char **

    @@ -4749,19 +4935,19 @@ object to be used as a char ** object. int i = 0; $1 = (char **) malloc((size+1)*sizeof(char *)); for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); - if (PyString_Check(o)) - $1[i] = PyString_AsString(PyList_GetItem($input,i)); - else { - PyErr_SetString(PyExc_TypeError,"list must contain strings"); + PyObject *o = PyList_GetItem($input, i); + if (PyString_Check(o)) { + $1[i] = PyString_AsString(PyList_GetItem($input, i)); + } else { free($1); - return NULL; + PyErr_SetString(PyExc_TypeError, "list must contain strings"); + SWIG_fail; } } $1[i] = 0; } else { - PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; + PyErr_SetString(PyExc_TypeError, "not a list"); + SWIG_fail; } } @@ -4773,12 +4959,12 @@ object to be used as a char ** object. // Now a test function %inline %{ int print_args(char **argv) { - int i = 0; - while (argv[i]) { - printf("argv[%d] = %s\n", i,argv[i]); - i++; - } - return i; + int i = 0; + while (argv[i]) { + printf("argv[%d] = %s\n", i, argv[i]); + i++; + } + return i; } %} @@ -4805,10 +4991,10 @@ In the example, two different typemaps are used. The "in" typemap is used to receive an input argument and convert it to a C array. Since dynamic memory allocation is used to allocate memory for the array, the "freearg" typemap is used to later release this memory after the execution of -the C function. +the C function.

    -

    36.9.2 Expanding a Python object into multiple arguments

    +

    32.9.2 Expanding a Python object into multiple arguments

    @@ -4848,19 +5034,19 @@ previous example: $1 = PyList_Size($input); $2 = (char **) malloc(($1+1)*sizeof(char *)); for (i = 0; i < $1; i++) { - PyObject *o = PyList_GetItem($input,i); - if (PyString_Check(o)) - $2[i] = PyString_AsString(PyList_GetItem($input,i)); - else { - PyErr_SetString(PyExc_TypeError,"list must contain strings"); + PyObject *o = PyList_GetItem($input, i); + if (PyString_Check(o)) { + $2[i] = PyString_AsString(PyList_GetItem($input, i)); + } else { free($2); - return NULL; + PyErr_SetString(PyExc_TypeError, "list must contain strings"); + SWIG_fail; } } $2[i] = 0; } else { - PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; + PyErr_SetString(PyExc_TypeError, "not a list"); + SWIG_fail; } } @@ -4871,7 +5057,7 @@ previous example:

    -When writing a multiple-argument typemap, each of the types is referenced by a variable such +When writing a multiple-argument typemap, each of the types is referenced by a variable such as $1 or $2. The typemap code simply fills in the appropriate values from the supplied Python object.

    @@ -4920,14 +5106,14 @@ If you don't you'll get an error message along the lines of: Traceback (most recent call last): File "runme.py", line 3, in >module< example.foo(["foo", "bar", "spam", "1"]) -NotImplementedError: Wrong number or type of arguments for overloaded function 'foo'. +TypeError: Wrong number or type of arguments for overloaded function 'foo'. Possible C/C++ prototypes are: - foo(int,char **) + foo(int, char **) foo() -

    36.9.3 Using typemaps to return arguments

    +

    32.9.3 Using typemaps to return arguments

    @@ -4953,7 +5139,7 @@ A typemap can be used to handle this case as follows : %module outarg // This tells SWIG to treat an double * argument with name 'OutValue' as -// an output value. We'll append the value to the current result which +// an output value. We'll append the value to the current result which // is guaranteed to be a List object by SWIG. %typemap(argout) double *OutValue { @@ -4965,12 +5151,12 @@ A typemap can be used to handle this case as follows : if (!PyTuple_Check($result)) { PyObject *o2 = $result; $result = PyTuple_New(1); - PyTuple_SetItem($result,0,o2); + PyTuple_SetItem($result, 0, o2); } o3 = PyTuple_New(1); - PyTuple_SetItem(o3,0,o); + PyTuple_SetItem(o3, 0, o); o2 = $result; - $result = PySequence_Concat(o2,o3); + $result = PySequence_Concat(o2, o3); Py_DECREF(o2); Py_DECREF(o3); } @@ -4994,8 +5180,8 @@ no meaningful input value), an additional typemap can be written. For example:

    -%typemap(in,numinputs=0) double *OutValue(double temp) {
    -    $1 = &temp;
    +%typemap(in, numinputs=0) double *OutValue(double temp) {
    +  $1 = &temp;
     }
     
     
    @@ -5008,14 +5194,14 @@ function can now be used as follows:

    ->>> a = spam(4,5)
    +>>> a = spam(4, 5)
     >>> print a
     (0, 2.45, 5.0)
    ->>> x,y,z = spam(4,5)
    +>>> x, y, z = spam(4, 5)
     >>>
     
    -

    36.9.4 Mapping Python tuples into small arrays

    +

    32.9.4 Mapping Python tuples into small arrays

    @@ -5036,14 +5222,14 @@ This too, can be handled used typemaps as follows : %typemap(in) double[4](double temp[4]) { // temp[4] becomes a local variable int i; if (PyTuple_Check($input)) { - if (!PyArg_ParseTuple($input,"dddd",temp,temp+1,temp+2,temp+3)) { - PyErr_SetString(PyExc_TypeError,"tuple must have 4 elements"); - return NULL; + if (!PyArg_ParseTuple($input, "dddd", temp, temp+1, temp+2, temp+3)) { + PyErr_SetString(PyExc_TypeError, "tuple must have 4 elements"); + SWIG_fail; } $1 = &temp[0]; } else { - PyErr_SetString(PyExc_TypeError,"expected a tuple."); - return NULL; + PyErr_SetString(PyExc_TypeError, "expected a tuple."); + SWIG_fail; } } @@ -5055,7 +5241,7 @@ Python as follows :

    ->>> set_direction((0.5,0.0,1.0,-0.25))
    +>>> set_direction((0.5, 0.0, 1.0, -0.25))
     

    @@ -5064,7 +5250,7 @@ array, such an approach would not be recommended for huge arrays, but for small structures, this approach works fine.

    -

    36.9.5 Mapping sequences to C arrays

    +

    32.9.5 Mapping sequences to C arrays

    @@ -5077,22 +5263,22 @@ arrays of different sizes. To do this, you might write a typemap as follows: %typemap(in) double[ANY](double temp[$1_dim0]) { int i; if (!PySequence_Check($input)) { - PyErr_SetString(PyExc_TypeError,"Expecting a sequence"); - return NULL; + PyErr_SetString(PyExc_TypeError, "Expecting a sequence"); + SWIG_fail; } if (PyObject_Length($input) != $1_dim0) { - PyErr_SetString(PyExc_ValueError,"Expecting a sequence with $1_dim0 elements"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Expecting a sequence with $1_dim0 elements"); + SWIG_fail; } for (i =0; i < $1_dim0; i++) { - PyObject *o = PySequence_GetItem($input,i); - if (!PyFloat_Check(o)) { - Py_XDECREF(o); - PyErr_SetString(PyExc_ValueError,"Expecting a sequence of floats"); - return NULL; - } - temp[i] = PyFloat_AsDouble(o); - Py_DECREF(o); + PyObject *o = PySequence_GetItem($input, i); + if (!PyFloat_Check(o)) { + Py_XDECREF(o); + PyErr_SetString(PyExc_ValueError, "Expecting a sequence of floats"); + SWIG_fail; + } + temp[i] = PyFloat_AsDouble(o); + Py_DECREF(o); } $1 = &temp[0]; } @@ -5123,37 +5309,37 @@ to use a helper function instead. This will greatly reduce the amount of wrappe static int convert_darray(PyObject *input, double *ptr, int size) { int i; if (!PySequence_Check(input)) { - PyErr_SetString(PyExc_TypeError,"Expecting a sequence"); - return 0; + PyErr_SetString(PyExc_TypeError, "Expecting a sequence"); + return 0; } if (PyObject_Length(input) != size) { - PyErr_SetString(PyExc_ValueError,"Sequence size mismatch"); - return 0; + PyErr_SetString(PyExc_ValueError, "Sequence size mismatch"); + return 0; } for (i =0; i < size; i++) { - PyObject *o = PySequence_GetItem(input,i); - if (!PyFloat_Check(o)) { - Py_XDECREF(o); - PyErr_SetString(PyExc_ValueError,"Expecting a sequence of floats"); - return 0; - } - ptr[i] = PyFloat_AsDouble(o); - Py_DECREF(o); + PyObject *o = PySequence_GetItem(input, i); + if (!PyFloat_Check(o)) { + Py_XDECREF(o); + PyErr_SetString(PyExc_ValueError, "Expecting a sequence of floats"); + return 0; + } + ptr[i] = PyFloat_AsDouble(o); + Py_DECREF(o); } return 1; } %} %typemap(in) double [ANY](double temp[$1_dim0]) { - if (!convert_darray($input,temp,$1_dim0)) { - return NULL; - } - $1 = &temp[0]; + if (!convert_darray($input, temp, $1_dim0)) { + SWIG_fail; + } + $1 = &temp[0]; } -

    36.9.6 Pointer handling

    +

    32.9.6 Pointer handling

    @@ -5201,8 +5387,9 @@ is usually accessed as follows:

     Foo *f;
    -if (SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, SWIG_POINTER_EXCEPTION) == -1)
    -  return NULL;
    +if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0))) {
    +  SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
    +}
     
     PyObject *obj;
     obj = SWIG_NewPointerObj(f, SWIGTYPE_p_Foo, 0);
    @@ -5217,8 +5404,9 @@ variable $1_descriptor.  For example:
     
     %typemap(in) Foo * {
    -if ((SWIG_ConvertPtr($input,(void **) &$1, $1_descriptor,SWIG_POINTER_EXCEPTION)) == -1)
    -  return NULL;
    +  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
    +    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
    +  }
     }
     
    @@ -5231,9 +5419,9 @@ For example:
     %typemap(in) Foo * {
    -if ((SWIG_ConvertPtr($input,(void **) &$1, $descriptor(Foo *), 
    -                                               SWIG_POINTER_EXCEPTION)) == -1)
    -  return NULL;
    +  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $descriptor(Foo *), 0))) {
    +    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
    +  }
     }
     
    @@ -5248,9 +5436,168 @@ that has a this attribute. In addition, class object (if applicable).

    +

    32.9.7 Memory management when returning references to member variables

    -

    36.10 Docstring Features

    +

    +This example shows how to prevent premature garbage collection of objects when the underlying C++ class returns a pointer or reference to a member variable. +The example is a direct equivalent to this Java equivalent. +

    + +

    +Consider the following C++ code: +

    + +
    +
    +#include <iostream>
    +struct Wheel {
    +  int size;
    +  Wheel(int sz = 0) : size(sz) {}
    +  ~Wheel() { std::cout << "~Wheel" << std::endl; }
    +};
    +
    +class Bike {
    +  Wheel wheel;
    +public:
    +  Bike(int val) : wheel(val) {}
    +  Wheel& getWheel() { return wheel; }
    +};
    +
    +
    + +

    +and the following usage from Python after running the code through SWIG: +

    + + +
    +
    +bike = Bike(10)
    +wheel = bike.getWheel()
    +print("wheel size: {}".format(wheel.size))
    +
    +del bike  # Allow bike to be garbage collected
    +print("wheel size: {}".format(wheel.size))
    +
    +
    + +

    +Don't be surprised that if the resulting output gives strange results such as... +

    + +
    +
    +wheel size: 10
    +~Wheel
    +wheel size: 135019664
    +
    +
    + +

    +What has happened here is the garbage collector has collected the Bike instance as it doesn't think it is needed any more. +The proxy instance, wheel, contains a reference to memory that was deleted when the Bike instance was collected. +In order to prevent the garbage collector from collecting the Bike instance, a reference to the Bike must +be added to the wheel instance. +

    + +

    +You can do this by adding the reference when the getWheel() method +is called using one of three approaches: +

    + +

    +The easier, but less optimized, way is to use the %pythonappend directive +(see Adding additional Python code): +

    + +
    +
    +%pythonappend getWheel %{
    +  # val is the Wheel proxy, self is the Bike instance
    +  val.__bike_reference = self
    +%}
    +
    +
    + +

    +The code gets appended to the Python code generated for the +Bike::getWheel wrapper function, where we store the Bike proxy +instance onto the Wheel proxy instance before it is returned to the +caller as follows. +

    + +
    +
    +class Bike(object):
    +    ...
    +    def getWheel(self):
    +        val = _example.Bike_getWheel(self)
    +
    +        # val is the Wheel proxy, self is the Bike instance
    +        val.__bike_reference = self
    +
    +        return val
    +
    +
    + + +

    +The second option, which performs better and is required if you use the +-builtin option, is to set the reference in the CPython implementation: + +

    +
    +%extend Wheel {
    +// A reference to the parent class is added to ensure the underlying C++
    +// object is not deleted while the item is in use
    +%typemap(ret) Wheel& getWheel {
    +  PyObject *bike_reference_string = SWIG_Python_str_FromChar("__bike_reference");
    +  PyObject_SetAttr($result, bike_reference_string, $self);
    +  Py_DecRef(bike_reference_string);
    +}
    +}
    +
    +
    + +

    +The third approach, shown below, is an optimization of the above approach and creates the "__bike_reference" Python string object just once. +While this looks more complex, it is just a small variation on the above typemap plus a support function +bike_reference() in a fragment called bike_reference_function. +The bike_reference_init typemap generates code into the "init" section for an initial call to bike_reference() when the module +is initialized and is done to create the "__bike_reference" Python string singleton in a thread-safe manner. +

    + +
    +
    +%fragment("bike_reference_init", "init") {
    +  // Thread-safe initialization - initialize during Python module initialization
    +  bike_reference();
    +}
    +
    +%fragment("bike_reference_function", "header", fragment="bike_reference_init") {
    +
    +static PyObject *bike_reference() {
    +  static PyObject *bike_reference_string = SWIG_Python_str_FromChar("__bike_reference");
    +  return bike_reference_string;
    +}
    +
    +}
    +
    +%extend Wheel {
    +// A reference to the parent class is added to ensure the underlying C++
    +// object is not deleted while the item is in use
    +%typemap(ret, fragment="bike_reference_function") Wheel& getWheel %{
    +  PyObject_SetAttr($result, bike_reference(), $self);
    +%}
    +}
    +
    +
    + + + + +

    32.10 Docstring Features

    @@ -5278,7 +5625,7 @@ of your users much simpler.

    -

    36.10.1 Module docstring

    +

    32.10.1 Module docstring

    @@ -5303,7 +5650,7 @@ example:

     %define DOCSTRING
    -"The `XmlResource` class allows program resources defining menus, 
    +"The `XmlResource` class allows program resources defining menus,
     layout of controls on a panel, etc. to be loaded from an XML file."
     %enddef
     
    @@ -5312,7 +5659,7 @@ layout of controls on a panel, etc. to be loaded from an XML file."
     
    -

    36.10.2 %feature("autodoc")

    +

    32.10.2 %feature("autodoc")

    @@ -5340,7 +5687,7 @@ four levels for autodoc controlled by the value given to the feature, %feature("autodoc", "level"). The four values for level are covered in the following sub-sections. -

    36.10.2.1 %feature("autodoc", "0")

    +

    32.10.2.1 %feature("autodoc", "0")

    @@ -5369,7 +5716,7 @@ def function_name(*args, **kwargs):

    -

    36.10.2.2 %feature("autodoc", "1")

    +

    32.10.2.2 %feature("autodoc", "1")

    @@ -5394,7 +5741,7 @@ def function_name(*args, **kwargs): -

    36.10.2.3 %feature("autodoc", "2")

    +

    32.10.2.3 %feature("autodoc", "2")

    @@ -5442,7 +5789,7 @@ resulting in

     def function_name(*args, **kwargs):
    -  """
    +    """
         function_name(x, y, foo=None, bar=None) -> bool
     
         Parameters
    @@ -5456,7 +5803,7 @@ def function_name(*args, **kwargs):
     
    -

    36.10.2.4 %feature("autodoc", "3")

    +

    32.10.2.4 %feature("autodoc", "3")

    @@ -5482,7 +5829,7 @@ def function_name(*args, **kwargs): -

    36.10.2.5 %feature("autodoc", "docstring")

    +

    32.10.2.5 %feature("autodoc", "docstring")

    @@ -5501,7 +5848,7 @@ void GetPosition(int* OUTPUT, int* OUTPUT); -

    36.10.3 %feature("docstring")

    +

    32.10.3 %feature("docstring")

    @@ -5533,7 +5880,7 @@ with more than one line. -

    36.11 Python Packages

    +

    32.11 Python Packages

    Python has concepts of modules and packages. Modules are separate units of @@ -5592,15 +5939,14 @@ Python3 adds another option for packages with namespace packages). Implicit namespace packages no longer use __init__.py files. SWIG generated Python modules support implicit namespace packages. See -36.11.5 Implicit Namespace -Packages for more information. +Implicit namespace +packages for more information.

    -If you place a SWIG generated module into a Python package then there -are details concerning the way SWIG -searches for the wrapper module -that you may want to familiarize yourself with. +You can place a SWIG generated module into a Python package or keep as a global module, +details are covered a little later in +Location of modules.

    The way Python defines its modules and packages impacts SWIG users. Some @@ -5608,7 +5954,7 @@ users may need to use special features such as the package option in th %module directive or import related command line options. These are explained in the following sections.

    -

    36.11.1 Setting the Python package

    +

    32.11.1 Setting the Python package

    @@ -5662,7 +6008,7 @@ pkg1/pkg2/_foo.so # (shared library built from C/C++ code generated by SWI -

    36.11.2 Absolute and relative imports

    +

    32.11.2 Absolute and relative imports

    Suppose, we have the following hierarchy of files:

    @@ -5759,12 +6105,19 @@ class M2(pkg2.mod3.M3): pass -

    By default, SWIG would generate mod2.py proxy file with +

    By default, SWIG will generate mod2.py proxy file with import directive as in point 1. This can be changed with the -relativeimport command line option. The -relativeimport instructs -SWIG to organize imports as in point 2 (for Python < 2.7.0) or as in point 4 -for Python 2.7.0 and newer. This is a check done at the time the module is -imported. In short, if you have +SWIG to organize imports as in point 4 for Python 2.7.0 and newer. +

    + +

    +Compatibility Note: Versions of SWIG prior to SWIG-4.0.0 supported Python < 2.7.0 +and would organize the imports as in point 2 if an older version of Python was detected at runtime. +

    + +

    +In short, if you have mod2.i and mod3.i as above, then without -relativeimport SWIG will write

    @@ -5779,13 +6132,8 @@ write

    -from sys import version_info
    -if version_info >= (2, 7, 0):
    -    from . import pkg2
    -    import pkg1.pkg2.mod3
    -else:
    -    import pkg2.mod3
    -del version_info
    +from . import pkg2
    +from .pkg2 import mod3
     
    @@ -5797,7 +6145,7 @@ uses relative imports. Second case is, when one puts import directives in __init__.py to import symbols from submodules or subpackages and the submodule depends on other submodules (discussed later).

    -

    36.11.3 Enforcing absolute import semantics

    +

    32.11.3 Enforcing absolute import semantics

    As you may know, there is an incompatibility in import semantics (for the @@ -5823,7 +6171,7 @@ from __future__ import absolute_import -

    at the very beginning of his proxy *.py file. In SWIG, it may be +

    at the very beginning of your proxy *.py file. In SWIG, it may be accomplished with %pythonbegin directive as follows:

    @@ -5834,7 +6182,7 @@ from __future__ import absolute_import
    -

    36.11.4 Importing from __init__.py

    +

    32.11.4 Importing from __init__.py

    Imports in __init__.py are handy when you want to populate a @@ -5944,7 +6292,7 @@ class Bar(pkg3.foo.Foo): pass effect (note, that the Python 2 case also needs the -relativeimport workaround).

    -

    36.11.5 Implicit Namespace Packages

    +

    32.11.5 Implicit namespace packages

    Python 3.3 introduced @@ -5991,7 +6339,7 @@ packages you can place these files in the following configurations: -

    Finally suppose that your pure python code is stored in a .zip file or +

    Finally suppose that your pure Python code is stored in a .zip file or some other way (database, web service connection, etc). Python can load the robin.py module using a custom importer. But the _robin.so module will need to be located on a file system. Implicit namespace packages make this @@ -6022,109 +6370,280 @@ zipimporter requires python-3.5.1 or newer to work with subpackages.

    -

    36.11.6 Searching for the wrapper module

    +

    32.11.6 Location of modules

    When SWIG creates wrappers from an interface file, say foo.i, two Python modules are -created. There is a pure Python module module (foo.py) and C/C++ code which is -built and linked into a dynamically (or statically) loaded module _foo -(see the Preliminaries section for details). So, the interface +created. There is a pure Python module (foo.py) and C/C++ code which is +compiled and linked into a dynamically (or statically) loaded low-level module _foo +(see the Preliminaries section for details). So, the interface file really defines two Python modules. How these two modules are loaded is covered next.

    -The pure Python module needs to load the C/C++ module in order to link -to the wrapped C/C++ methods. To do this it must make some assumptions -about what package the C/C++ module may be located in. The approach the -pure Python module uses to find the C/C++ module is as follows: +The pure Python module needs to load the C/C++ module in order to call +the wrapped C/C++ methods. To do this it must make some assumptions +about the location of the C/C++ module. +There are two configurations that are supported by default.

      -
    1. The pure Python module, foo.py, tries to load the C/C++ module, _foo, from the same package foo.py is - located in. The package name is determined from the __name__ - attribute given to foo.py by the Python loader that imported - foo.py. If foo.py is not in a package then _foo is loaded - as a global module.

      +
    2. Both modules in the same package

    3. -
    4. If the above import of _foo results in an ImportError - being thrown, then foo.py makes a final attempt to load _foo - as a global module.

      +
    5. Both modules are global

    -As an example suppose foo.i is compiled into foo.py and _foo.so. Assuming -/dir is on PYTHONPATH, then the two modules can be installed and used in the -following ways: +Additional configurations are supported but require custom import code.

    -

    36.11.6.1 Both modules in the same package

    +

    +The following sub-sections look more closely at the two default configurations as well as some customized configurations. +An input interface file, foo.i, results in the two modules foo.py and _foo.so for each of the configurations. +

    + +

    32.11.6.1 Both modules in the same package

    -

    Both modules are in one package:

    -
    +

    +In this configuration, the pure Python module, foo.py, tries to load the C/C++ module, _foo, from the same package foo.py is +located in. The package name is determined from the __package__ +attribute if available, see PEP 366. Otherwise it is derived from the __name__ +attribute given to foo.py by the Python loader that imported foo.py. +The interface file for this configuration would contain: +

    + +
    -/dir/package/foo.py
    -/dir/package/__init__.py
    -/dir/package/_foo.so
    +%module(package="mypackage") foo
     
    -

    And imported with

    + +

    The location of the files could be as follows:

    -from package import foo
    +/dir/mypackage/foo.py
    +/dir/mypackage/__init__.py
    +/dir/mypackage/_foo.so
    +
    +
    + +

    Assuming /dir/ is in PYTHONPATH, the module can be imported using

    + +
    +
    +from mypackage import foo
     
    -

    36.11.6.2 Split modules

    +

    32.11.6.2 Both modules are global

    -

    The pure python module is in a package and the C/C++ module is global:

    -
    +

    +In this configuration, there are no packages. +If foo.py is not in a package, that is, it is a global module, then _foo is loaded +as a global module. +The interface file for this configuration would contain: +

    + +
    -/dir/package/foo.py
    -/dir/package/__init__.py
    -/dir/_foo.so
    -
    -
    -

    And imported with

    -
    -
    -from package import foo
    +%module foo
     
    - -

    36.11.6.3 Both modules are global

    - - -

    Both modules are global:

    +

    The location of the files could be as follows:

     /dir/foo.py
     /dir/_foo.so
     
    -

    And imported with

    -
    + +

    Assuming /dir/ is in PYTHONPATH, the module can be imported using

    + +
     import foo
     
    -

    -If _foo is statically linked into an embedded Python interpreter, then it may or -may not be in a Python package. This depends in the exact way the module was -loaded statically. The above search order will still be used for statically -loaded modules. So, one may place the module either globally or in a package -as desired. +

    32.11.6.3 Split modules custom configuration

    + + +

    In this non-standard 'split module' configuration, the pure Python module is in a package and the low level C/C++ module is global. +This configuration is not generally recommended and is not supported by default as it needs a custom configuration. +The module import code customization required is via the moduleimport attribute in the %module directive. +The next sub-section elaborates further on this. +The interface file for this split module configuration would contain:

    -

    36.11.6.4 Statically linked C modules

    +
    +
    +%module(package="mypackage", moduleimport="import _foo") foo
    +
    +
    + +

    +When using -builtin, use the following instead (the reasons are also covered shortly in the next sub-section): +

    + +
    +
    +%module(package="mypackage", moduleimport="from _foo import *") foo
    +
    +
    + +

    The location of the files could be as follows:

    +
    +
    +/dir/mypackage/foo.py
    +/dir/mypackage/__init__.py
    +/dir/_foo.so
    +
    +
    + +

    Assuming /dir/ is in PYTHONPATH, the module can be imported using

    + +
    +
    +from mypackage import foo
    +
    +
    + +

    +Compatibility Note: Versions of SWIG prior to SWIG-4.0.0 supported split modules without the above customization. +However, this had to be removed as the default import code often led to confusion due to obfuscation of genuine Python ImportError problems. +Using one of the two default configurations is the recommended approach now. +

    + + +

    32.11.6.4 More on customizing the module import code

    + + +

    +The Python code implementing the default import logic is shown below. It supports the two configurations described earlier, that is, +either both modules are in a package or loading both as global modules. +The code is generated into the pure Python module, foo.py, and merely imports the low-level _foo module. +

    + +
    +
    +if __package__ or '.' in __name__:
    +    from . import _foo
    +else:
    +    import _foo
    +
    +
    + +

    +This import code implementation is non-trivial but it can be replaced with custom code providing opportunities to make it simpler and/or more flexible. +This is not normally recommended though unless you have a good understanding of the intricacies of importing Python modules. +The custom code can be specified by setting the moduleimport option of the %module directive with the appropriate import code. For example: +

    + +
    +
    +%module(moduleimport="import _foo") foo
    +
    +
    + +

    +This will replace the default import logic above and generate the following into the pure Python module, foo.py: +

    + +
    +
    +import _foo
    +
    +
    + +

    +In fact the above is a simplification customization for the configuration where both modules are global; +it removes the logic for also handling the modules being in a package. +

    + +

    +There is a special variable, $module, which is expanded into the low-level C/C++ module name, _foo in the case above. +The identical output would be generated if instead the following had been used: +

    + +
    +
    +%module(moduleimport="import $module") foo
    +
    +
    + +

    +When you have many lines you can retain the easy +readability of the %module directive by using a macro. For +example: +

    + +
    +
    +%define MODULEIMPORT
    +"
    +print 'Loading low-level module $module'
    +import $module
    +print 'Module has loaded'
    +"
    +%enddef
    +
    +%module(moduleimport=MODULEIMPORT) foo
    +
    +
    + +

    +This will of course generate the following into the pure Python module: +

    + +
    +
    +print 'Loading low-level module $module'
    +import _foo
    +print 'Module has loaded'
    +
    +
    + +

    +When using the -builtin option, the link between the pure Python module and the low-level C/C++ module is slightly different as +all the objects from the low-level module are imported directly into the pure Python module. +The default import loading code is thus different: +

    + +
    +
    +if __package__ or '.' in __name__:
    +    from ._foo import *
    +else:
    +    from _foo import *
    +
    +
    + +

    +Any customizations must import the code in a similar manner. +The best way to support both with and without -builtin is to make use of the SWIGPYTHON_BUILTIN macro which is defined when -builtin is specified. +The following will do this for the split modules case above. +

    + + +
    +
    +#if defined(SWIGPYTHON_BUILTIN) /* defined when using -builtin */
    +%module(package="mypackage", moduleimport="from $module import *") foo
    +#else
    +%module(package="mypackage", moduleimport="import $module") foo
    +#endif
    +
    +
    + +

    32.11.6.5 Statically linked C modules

    It is strongly recommended to use dynamically linked modules for the C @@ -6133,7 +6652,7 @@ If for some reason you still need to link the C module of the pair of Python modules generated by SWIG into your interpreter, then this section provides some details on how this impacts the pure Python modules ability to locate the other part of the pair. -Please also see the Static Linking section. +Please also see the Static Linking section.

    When Python is extended with C code the Python interpreter needs to be @@ -6150,7 +6669,7 @@ new SWIG C module exists. which would have normally been called when the shared object was dynamically loaded. The specific name of this method is not given here because statically linked modules are not encouraged with SWIG -(Static Linking). However one can find this +(Static Linking). However one can find this init function in the C file generated by SWIG.

    @@ -6162,8 +6681,8 @@ they treat it affects how the pure Python module will be able to locate the C module.

    -

    The details concerning this are covered completly in the documentation -for Python itself. Links to the relavent sections follow: +

    The details concerning this are covered completely in the documentation +for Python itself. Links to the relevant sections follow:

      @@ -6173,21 +6692,21 @@ for Python itself. Links to the relavent sections follow:

      There are two keys things to understand. The first is that in Python 2 the init() function returns void. In Python 3 the init() function -returns a PyObject * which points to the new module. Secondly, when +returns a PyObject * which points to the new module. Secondly, when you call the init() method manually, you are the Python importer. So, you determine which package the C module will be located in.

      So, if you are using Python 3 it is important that you follow what is described in the Python documentation linked above. In particular, you can't -simply call the init() function generated by SWIG and cast the PyObject +simply call the init() function generated by SWIG and cast the PyObject pointer it returns over the side. If you do then Python 3 will have no idea that your C module exists and the pure Python half of your wrapper will not be able to find it. You need to register your module with the Python interpreter as described in the Python docs.

      -

      With Python 2 things are somewhat more simple. In this case the init function +

      With Python 2 things are somewhat more simple. In this case the init() function returns void. Calling it will register your new C module as a global module. The pure Python part of the SWIG wrapper will be able to find it because it tries both the pure Python module it is part of and the global @@ -6196,17 +6715,15 @@ module then you will either need to refer to the Python documentation on how to do this (remember you are now the Python importer) or use dynamic linking.

      -

      36.12 Python 3 Support

      +

      32.12 Python 3 Support

      -SWIG is able to support Python 3.0. The wrapper code generated by -SWIG can be compiled with both Python 2.x or 3.0. Further more, by +SWIG is able to support Python 3.x. The wrapper code generated by +SWIG can be compiled with both Python 2.x or 3.x. Further more, by passing the -py3 command line option to SWIG, wrapper code with some Python 3 specific features can be generated (see below -subsections for details of these features). The -py3 option also -disables some incompatible features for Python 3, such as --classic. +subsections for details of these features).

      There is a list of known-to-be-broken features in Python 3: @@ -6219,11 +6736,11 @@ There is a list of known-to-be-broken features in Python 3:

    -The following are Python 3.0 new features that are currently supported by +The following are Python 3 new features that are currently supported by SWIG.

    -

    36.12.1 Function annotation

    +

    32.12.1 Function annotation

    @@ -6256,12 +6773,12 @@ For detailed usage of function annotation, see PEP 3107.

    -

    36.12.2 Buffer interface

    +

    32.12.2 Buffer interface

    -Buffer protocols were revised in Python 3. SWIG also gains a series of -new typemaps to support buffer interfaces. These typemap macros are +SWIG has a series of +typemaps to support buffer interfaces. These typemap macros are defined in pybuffer.i, which must be included in order to use them. By using these typemaps, your wrapped function will be able to accept any Python object that exposes a suitable buffer interface. @@ -6278,15 +6795,15 @@ void get_path(char *s);

    Then you can write a typemap like this: (the following example is -applied to both Python 3.0 and 2.6, since the bytearray type -is backported to 2.6. +applied to both Python 2 and 3, since the bytearray type +was backported to 2.6.

     %include <pybuffer.i>
     %pybuffer_mutable_string(char *str);
    -void get_path(char *s);
    +void get_path(char *str);
     

    @@ -6333,7 +6850,7 @@ In Python: >>> snprintf(buf, "Hello world!") >>> print(buf) bytearray(b'Hello\x00') ->>> +>>>

    @@ -6369,7 +6886,7 @@ bytearray(b'FOO\x00')

    Both %pybuffer_mutable_binary and %pybuffer_mutable_string -require the provided buffer to be mutable, eg. they can accept a +require the provided buffer to be mutable, eg. they can accept a bytearray type but can't accept an immutable byte type.

    @@ -6386,7 +6903,7 @@ type. This macro maps an object's buffer to a pointer parm and a size size_parm. It is similar to %pybuffer_mutable_binary, except the -%pybuffer_binary an accept both mutable and immutable +%pybuffer_binary can accept both mutable and immutable buffers. As a result, the wrapped function should not modify the buffer.

    @@ -6408,13 +6925,14 @@ modify the buffer.
    -

    36.12.3 Abstract base classes

    +

    32.12.3 Abstract base classes

    By including pyabc.i and using the -py3 command line option when calling SWIG, the proxy classes of the STL containers -will automatically gain an appropriate abstract base class. For +will automatically gain an appropriate abstract base class from the +collections.abc module. For example, the following SWIG interface:

    @@ -6431,8 +6949,8 @@ namespace std {

    will generate a Python proxy class Mapii inheriting from -collections.MutableMap and a proxy class IntList -inheriting from collections.MutableSequence. +collections.abc.MutableMap and a proxy class IntList +inheriting from collections.abc.MutableSequence.

    @@ -6441,7 +6959,7 @@ used to define an abstract base class for your own C++ class:

    -%pythonabc(MySet, collections.MutableSet);
    +%pythonabc(MySet, collections.abc.MutableSet);
     

    @@ -6449,7 +6967,15 @@ For details of abstract base class, please see PEP 3119.

    -

    36.12.4 Byte string output conversion

    +

    +Compatibility Note: SWIG-4.0.0 changed the base classes to use the +collections.abc module instead of collections due to the deprecation +of the classes in the collections module in Python 3.7. +The collections.abc module was introduced in Python 3.3 and hence this feature +requires Python 3.3 or later. +

    + +

    32.12.4 Byte string output conversion

    @@ -6466,18 +6992,21 @@ string that cannot be completely decoded as UTF-8:

     %module example
     
    -%include <std_string.i>
    -
     %inline %{
     
    -const char* non_utf8_c_str(void) {
    -        return "h\xe9llo w\xc3\xb6rld";
    +const char * non_utf8_c_str(void) {
    +  return "h\xe9llo w\xc3\xb6rld";
    +}
    +
    +void instring(const char *s) {
    +  ...
     }
     
     %}
     

    +Note that "\xe9" is an invalid UTF-8 encoding, but "\xc3\xb6" is valid. When this method is called from Python 3, the return value is the following text string:

    @@ -6535,6 +7064,20 @@ For more details about the surrogateescape error handler, please see PEP 383.

    +

    +When Python 3 strings are passed to the C/C++ layer, they are expected to be valid UTF8 Unicode strings too. +For example, when the instring method above is wrapped and called, any invalid UTF8 Unicode code strings +will result in a TypeError because the attempted conversion fails: +

    + +
    +>>> example.instring('h\xe9llo')
    +>>> example.instring('h\udce9llo')
    +Traceback (most recent call last):
    +  File "<stdin>", line 1, in <module>
    +TypeError: in method 'instring', argument 1 of type 'char const *'
    +
    +

    In some cases, users may wish to instead handle all byte strings as bytes objects in Python 3. This can be accomplished by adding @@ -6613,7 +7156,7 @@ overloads taking both std::string (as Python bytes) and std::wstring (as Python unicode).

    -

    36.12.5 Python 2 Unicode

    +

    32.12.5 Python 2 Unicode

    @@ -6685,6 +7228,110 @@ the first is allowing unicode conversion and the second is explicitly prohibiting it.

    +

    32.13 Support for Multithreaded Applications

    + + +

    By default, SWIG does not enable support for multithreaded Python applications. More +specifically, the Python wrappers generated by SWIG will not release the + Python's interpreter's Global Interpreter Lock (GIL) when wrapped C/C++ code is +entered. Hence, while any of the wrapped C/C++ code is executing, the Python interpreter +will not be able to run any other threads, even if the wrapped C/C++ code is waiting + in a blocking call for something like network or disk IO. + + Fortunately, SWIG does have the ability to enable multithreaded support and automatic + release of the GIL either for all wrapped code in a module or on a more selective basis. The user + interface for this is described in the next section. +

    + +

    32.13.1 UI for Enabling Multithreading Support

    + + +

    The user interface is as follows:

    +
      +
    1. Module thread support can be enabled in two ways:

      +
        +
      • +

        + The -threads SWIG Python option at the command line (or in setup.py): +

        +
        $ swig -python -threads example.i
        +
      • +
      • +

        + The threads module option in the *.i template file: +

        +
        %module("threads"=1)
        +
      • +
      +
    2. +
    3. You can disable thread support for a given method:

      +
      %feature("nothread") method;
      + or +
      %nothread method;
      +
    4. +
    5. You can partially disable thread support for a given method:

      +
        +
      • To disable the C++/Python thread protection:

        +
        %feature("nothreadblock") method;
        + or +
        %nothreadblock method;
        +
      • +
      • +

        To disable the Python/C++ thread protection

        +
        %feature("nothreadallow") method;
        + or +
        %nothreadallow method;
        +
      • +
      +
    6. +
    + +

    32.13.2 Multithread Performance

    + + +

    + For the curious about performance, here are some numbers for the profiletest.i test, + which is used to check the speed of the wrapped code: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Thread ModeExecution Time (sec)Comment
    Single Threaded9.6no "-threads" option given
    Fully Multithreaded15.5"-threads" option = 'allow' + 'block'
    No Thread block12.2only 'allow'
    No Thread Allow13.6only block'
    + +

    + Fully threaded code decreases the wrapping performance by + around 60%. If that is important to your application, you + can tune each method using the different 'nothread', + 'nothreadblock' or 'nothreadallow' features as + needed. Note that for some methods deactivating the + 'thread block' or 'thread allow' code is not an option, + so, be careful. +

    + diff --git a/Doc/Manual/R.html b/Doc/Manual/R.html index 9b5993bff..45e5541d0 100644 --- a/Doc/Manual/R.html +++ b/Doc/Manual/R.html @@ -7,7 +7,7 @@ -

    37 SWIG and R

    +

    33 SWIG and R

      @@ -34,7 +34,7 @@ compile and run an R interface to QuantLib running on Mandriva Linux with gcc. The R bindings also work on Microsoft Windows using Visual C++.

      -

      37.1 Bugs

      +

      33.1 Bugs

      @@ -46,7 +46,7 @@ Currently the following features are not implemented or broken:

    • C Array wrappings
    -

    37.2 Using R and SWIG

    +

    33.2 Using R and SWIG

    @@ -129,7 +129,7 @@ These two files can be loaded in any order

  • If you do not set the output file name appropriately, you might see errors like
    -> fact(4)
    +> fact(4)
     Error in .Call("R_swig_fact", s_arg1, as.logical(.copy), PACKAGE = "example") :
       "R_swig_fact" not available for .Call() for package "example"
     
    @@ -137,7 +137,7 @@ Error in .Call("R_swig_fact", s_arg1, as.logical(.copy), PACKAGE = "example") :
  • Make sure the architecture of the shared library(x64 for instance), matches the architecture of the R program you want to load your shared library into -

    37.3 Precompiling large R files

    +

    33.3 Precompiling large R files

    In cases where the R file is large, one make save a lot of loading @@ -146,7 +146,7 @@ file makeRData.R which contains the following
     source('BigFile.R')
    -save(list=ls(all=TRUE),file="BigFile.RData", compress=TRUE)
    +save(list=ls(all=TRUE), file="BigFile.RData", compress=TRUE)
     q(save="no")
     
    @@ -155,7 +155,7 @@ will save a large amount of loading time. -

    37.4 General policy

    +

    33.4 General policy

    @@ -164,7 +164,7 @@ wrapping over the underlying functions and rely on the R type system to provide R syntax.

    -

    37.5 Language conventions

    +

    33.5 Language conventions

    @@ -173,7 +173,7 @@ and [ are overloaded to allow for R syntax (one based indices and slices)

    -

    37.6 C++ classes

    +

    33.6 C++ classes

    @@ -185,13 +185,53 @@ keep track of the pointer object which removes the necessity for a lot of the proxy class baggage you see in other languages.

    -

    37.7 Enumerations

    +

    33.7 Enumerations

    -enumerations are characters which are then converted back and forth to -ints before calling the C routines. All of the enumeration code is -done in R. +R doesn't have a native enumeration type. Enumerations are represented +as character strings in R, with calls to R functions that convert back +and forth between integers. + +The details of enumeration names and contents are stored in hidden R +environments, which are named according the the enumeration name - for +example, an enumeration colour: +

    +enum colour { red=-1, blue, green = 10 };
    +
    + +will be initialized by the following call in R: +
    +defineEnumeration("_colour",
    + .values=c("red" = .Call('R_swig_colour_red_get',FALSE, PACKAGE='enum_thorough'),
    +"blue" = .Call('R_swig_colour_blue_get',FALSE, PACKAGE='enum_thorough'),
    +"green" = .Call('R_swig_colour_green_get',FALSE, PACKAGE='enum_thorough')))
    +
    +
    + +

    +which will create an environment named .__E___colour. The enumeration +values are initialised via calls to C/C++ code, allowing complex +values for enumerations to be used. Calls to the C/C++ code require +the compiled library to be loaded, so a delayedAssign is employed +within defineEnumeration in order to allow the code to be easily used in R +packages. + +The user typically does not need to access the enumeration lookup +functions or know the name of the enumeration type used by +R. Attributes containing the type information are attached by swig to +functions requiring enumeration arguments or returning enumeration +values, and those attributes are used to identify and access the +appropriate environments and thus translate between characters +and integers. + +The relevant functions, for debugging purposes, are enumToInteger and +enumFromInteger. + +Anonymous enumerations are ignored by the binding generation process, +leaving no way of accessing the value of anonymous enumerations from R +code. +

    diff --git a/Doc/Manual/Ruby.html b/Doc/Manual/Ruby.html index cfb99e792..3cfd1292c 100644 --- a/Doc/Manual/Ruby.html +++ b/Doc/Manual/Ruby.html @@ -8,7 +8,7 @@ -

    38 SWIG and Ruby

    +

    34 SWIG and Ruby

      @@ -149,10 +149,10 @@

      This chapter describes SWIG's support of Ruby.

      -

      38.1 Preliminaries

      +

      34.1 Preliminaries

      -

      SWIG 3.0 is known to work with Ruby versions 1.8 and later. +

      SWIG 4.0 is known to work with Ruby versions 1.9 and later. Given the choice, you should use the latest stable version of Ruby. You should also determine if your system supports shared libraries and dynamic loading. SWIG will work with or without dynamic loading, but @@ -164,7 +164,7 @@ read the "SWIG Basics" chapter. It is also assumed that the reader has a basic understanding of Ruby.

      -

      38.1.1 Running SWIG

      +

      34.1.1 Running SWIG

      To build a Ruby module, run SWIG using the -ruby @@ -188,36 +188,21 @@ if compiling a C++ extension) that contains all of the code needed to build a Ruby extension module. To finish building the module, you need to compile this file and link it with the rest of your program.

      -

      38.1.2 Getting the right header files

      +

      34.1.2 Getting the right header files

      In order to compile the wrapper code, the compiler needs the ruby.h -header file. This file is usually contained in a directory such as

      - -
      -
      /usr/lib/ruby/1.8/x86_64-linux-gnu/ruby.h
      -/usr/include/ruby-2.1.0/ruby.h
      -
      -
      - -

      The exact location may vary on your machine, but the above -location is typical. If you are not entirely sure where Ruby is -installed, you can run Ruby to find out. For example:

      +header file and its dependencies, notably ruby/config.h which is +found in a different, architecture-dependent, directory. The best way to find +the compiler options needed to compile the code is to ask Ruby itself:

      -
      $ ruby -e 'puts $:.join("\n")'
      -/usr/local/lib/site_ruby/2.1.0
      -/usr/local/lib/x86_64-linux-gnu/site_ruby
      -/usr/local/lib/site_ruby
      -/usr/lib/ruby/vendor_ruby/2.1.0
      -/usr/lib/x86_64-linux-gnu/ruby/vendor_ruby/2.1.0
      -/usr/lib/ruby/vendor_ruby
      -/usr/lib/ruby/2.1.0
      -/usr/lib/x86_64-linux-gnu/ruby/2.1.0
      +
      $ ruby -rrbconfig -e 'puts "-I#{RbConfig::CONFIG[%q{rubyhdrdir}]} -I#{RbConfig::CONFIG[%q{rubyarchhdrdir}]}"'
      +-I/usr/include/ruby-2.1.0 -I/usr/include/x86_64-linux-gnu/ruby-2.1.0
       
      -

      38.1.3 Compiling a dynamic module

      +

      34.1.3 Compiling a dynamic module

      Ruby extension modules are typically compiled into shared @@ -287,10 +272,10 @@ processes). Other compilers may need a different option specified instead of

      If in doubt, consult the manual pages for your compiler and linker to determine the correct set -of options. You might also check the SWIG Wiki +of options. You might also check the SWIG Wiki for additional information.

      -

      38.1.4 Using your module

      +

      34.1.4 Using your module

      Ruby module names must be capitalized, @@ -320,7 +305,7 @@ begins with:

      will result in an extension module using the feature name "example" and Ruby module name "Example".

      -

      38.1.5 Static linking

      +

      34.1.5 Static linking

      An alternative approach to dynamic linking is to rebuild the @@ -335,7 +320,7 @@ finding the Ruby source, adding an entry to the ext/Setup file, adding your directory to the list of extensions in the file, and finally rebuilding Ruby.

      -

      38.1.6 Compilation of C++ extensions

      +

      34.1.6 Compilation of C++ extensions

      On most machines, C++ extension modules should be linked @@ -367,7 +352,7 @@ $libs = append_library($libs, "supc++") create_makefile('example')

    -

    38.2 Building Ruby Extensions under Windows 95/NT

    +

    34.2 Building Ruby Extensions under Windows 95/NT

    Building a SWIG extension to Ruby under Windows 95/NT is @@ -392,7 +377,7 @@ order to build extensions, you may need to download the source distribution to the Ruby package, as you will need the Ruby header files.

    -

    38.2.1 Running SWIG from Developer Studio

    +

    34.2.1 Running SWIG from Developer Studio

    If you are developing your application within Microsoft @@ -456,13 +441,13 @@ Foo = 3.0 -

    38.3 The Ruby-to-C/C++ Mapping

    +

    34.3 The Ruby-to-C/C++ Mapping

    This section describes the basics of how SWIG maps C or C++ declarations in your SWIG interface files to Ruby constructs.

    -

    38.3.1 Modules

    +

    34.3.1 Modules

    The SWIG %module directive specifies @@ -534,7 +519,7 @@ option to wrap everything into the global module, take care that the names of your constants, classes and methods don't conflict with any of Ruby's built-in names.

    -

    38.3.2 Functions

    +

    34.3.2 Functions

    Global functions are wrapped as Ruby module methods. For @@ -568,7 +553,7 @@ irb(main):002:0> Example.fact(4) 24 -

    38.3.3 Variable Linking

    +

    34.3.3 Variable Linking

    C/C++ global variables are wrapped as a pair of singleton @@ -630,7 +615,7 @@ directive. For example:

    effect until it is explicitly disabled using %mutable.

    -

    38.3.4 Constants

    +

    34.3.4 Constants

    C/C++ constants are wrapped as module constants initialized @@ -658,7 +643,7 @@ irb(main):002:0> Example::PI 3.14159 -

    38.3.5 Pointers

    +

    34.3.5 Pointers

    "Opaque" pointers to arbitrary C/C++ types (i.e. types that @@ -682,7 +667,7 @@ returns an instance of an internally generated Ruby class:

    A NULL pointer is always represented by the Ruby nil object.

    -

    38.3.6 Structures

    +

    34.3.6 Structures

    C/C++ structs are wrapped as Ruby classes, with accessor @@ -787,7 +772,7 @@ void Bar_f_set(Bar *b, Foo *val) { } -

    38.3.7 C++ classes

    +

    34.3.7 C++ classes

    Like structs, C++ classes are wrapped by creating a new Ruby @@ -842,7 +827,7 @@ Ale 3 -

    38.3.8 C++ Inheritance

    +

    34.3.8 C++ Inheritance

    The SWIG type-checker is fully aware of C++ inheritance. @@ -995,7 +980,7 @@ inherit from both Base1 and Base2 (i.e. they exhibit "Duck Typing").

    -

    38.3.9 C++ Overloaded Functions

    +

    34.3.9 C++ Overloaded Functions

    C++ overloaded functions, methods, and constructors are @@ -1014,7 +999,7 @@ void foo(char *c); irb(main):002:0> foo("Hello") # foo(char *c) -

    Similarly, if you have a class like this,

    +

    Similarly, if you have a class like this,

    class Foo {
    @@ -1085,7 +1070,7 @@ arises--in this case, the first declaration takes precedence. 

    Please refer to the "SWIG and C++" chapter for more information about overloading.

    -

    38.3.10 C++ Operators

    +

    34.3.10 C++ Operators

    For the most part, overloaded operators are handled @@ -1127,7 +1112,7 @@ c = Example.add_complex(a, b)

    is discussed in the section on operator overloading.

    -

    38.3.11 C++ namespaces

    +

    34.3.11 C++ namespaces

    SWIG is aware of C++ namespaces, but namespace names do not @@ -1141,7 +1126,7 @@ like this,

    namespace foo { int fact(int n); struct Vector { - double x,y,z; + double x, y, z; }; };
    @@ -1184,7 +1169,7 @@ and create extension modules for each namespace separately. If your program utilizes thousands of small deeply nested namespaces each with identical symbol names, well, then you get what you deserve.

    -

    38.3.12 C++ templates

    +

    34.3.12 C++ templates

    C++ templates don't present a huge problem for SWIG. However, @@ -1210,7 +1195,7 @@ struct pair { ~pair(); }; -%template(Pairii) pair<int,int>; +%template(Pairii) pair<int, int>;

    In Ruby:

    @@ -1226,7 +1211,7 @@ irb(main):004:0> p.second 4 -

    38.3.13 C++ Standard Template Library (STL)

    +

    34.3.13 C++ Standard Template Library (STL)

    On a related note, the standard SWIG library contains a @@ -1273,7 +1258,7 @@ v.each { |x| puts x } 3 4 v.delete_if { |x| x == 3 } -=> [2,4] +=> [2, 4]

    The SWIG Ruby module provides also the ability for all the STL @@ -1303,7 +1288,7 @@ include NativeVector v = NativeVector.new v << 1 -v << [1,2] +v << [1, 2] v << 'hello' class A; end @@ -1311,7 +1296,7 @@ class A; end v << A.new puts v -=> [1, [1,2], 'hello', #<A:0x245325>] +=> [1, [1, 2], 'hello', #<A:0x245325>] @@ -1319,7 +1304,7 @@ puts v shown in these examples. More details can be found in the SWIG and C++ chapter.

    -

    38.3.14 C++ STL Functors

    +

    34.3.14 C++ STL Functors

    Some containers in the STL allow you to modify their default @@ -1368,19 +1353,19 @@ a << 1 a << 2 a << 3 a -=> [1,2,3] +=> [1, 2, 3] # Custom sorting behavior defined by a Ruby proc -b = IntSet.new( proc { |a,b| a > b } ) +b = IntSet.new( proc { |a, b| a > b } ) b << 1 b << 2 b << 3 b -=> [3,2,1] +=> [3, 2, 1] -

    38.3.15 C++ STL Iterators

    +

    34.3.15 C++ STL Iterators

    The STL is well known for the use of iterators. There @@ -1463,10 +1448,10 @@ i

    If you'd rather have STL classes without any iterators, you should define -DSWIG_NO_EXPORT_ITERATOR_METHODS when running swig.

    -

    38.3.16 C++ Smart Pointers

    +

    34.3.16 C++ Smart Pointers

    -

    38.3.16.1 The shared_ptr Smart Pointer

    +

    34.3.16.1 The shared_ptr Smart Pointer

    @@ -1477,7 +1462,7 @@ in the shared_ptr smart pointer -

    38.3.16.2 Generic Smart Pointers

    +

    34.3.16.2 Generic Smart Pointers

    In certain C++ programs, it is common to use classes that @@ -1493,7 +1478,7 @@ like this:

    } -

    Then, if you have a class like this,

    +

    Then, if you have a class like this,

    class Foo {
    @@ -1542,7 +1527,7 @@ method. For example: 

    irb(main):004:0> f = p.__deref__() # Returns underlying Foo *
    -

    38.3.17 Cross-Language Polymorphism

    +

    34.3.17 Cross-Language Polymorphism

    SWIG's Ruby module supports cross-language polymorphism @@ -1551,7 +1536,7 @@ module. Rather than duplicate the information presented in the 38.3.17.1 Exception Unrolling +

    34.3.17.1 Exception Unrolling

    Whenever a C++ director class routes one of its virtual @@ -1574,7 +1559,7 @@ method is "wrapped" using the rb_rescue2() function from Ruby's C API. If any Ruby exception is raised, it will be caught here and a C++ exception is raised in its place.

    -

    38.4 Naming

    +

    34.4 Naming

    Ruby has several common naming conventions. Constants are @@ -1612,7 +1597,7 @@ generated by SWIG, it is turned off by default in SWIG 1.3.28. However, it is planned to become the default option in future releases.

    -

    38.4.1 Defining Aliases

    +

    34.4.1 Defining Aliases

    It's a fairly common practice in the Ruby built-ins and @@ -1665,7 +1650,7 @@ a comma-separated list of aliases to the %alias directive, e.g.

    -
    %alias MyArray::length "amount,quantity,size";
    +
    %alias MyArray::length "amount, quantity, size";

    From an end-user's standpoint, there's no functional @@ -1682,7 +1667,7 @@ matching rules used for other kinds of features apply (see the chapter on "Customization Features") for more details).

    -

    38.4.2 Predicate Methods

    +

    34.4.2 Predicate Methods

    Ruby methods that return a boolean value and end in a @@ -1731,7 +1716,7 @@ using SWIG's "features" mechanism and so the same name matching rules used for other kinds of features apply (see the chapter on "Customization Features") for more details).

    -

    38.4.3 Bang Methods

    +

    34.4.3 Bang Methods

    Ruby methods that modify an object in-place and end in an @@ -1763,7 +1748,7 @@ using SWIG's "features" mechanism and so the same name matching rules used for other kinds of features apply (see the chapter on "Customization Features") for more details).

    -

    38.4.4 Getters and Setters

    +

    34.4.4 Getters and Setters

    Often times a C++ library will expose properties through @@ -1798,7 +1783,7 @@ irb(main):003:0> puts foo.value %rename("value=") Foo::setValue(int value); -

    38.5 Input and output parameters

    +

    34.5 Input and output parameters

    A common problem in some C programs is handling parameters @@ -1835,10 +1820,10 @@ int sub(int *INPUT, int *INPUT);

    In Ruby, this allows you to pass simple values. For example:

    -
    a = Example.add(3,4)
    +
    a = Example.add(3, 4)
     puts a
     7
    -b = Example.sub(7,4)
    +b = Example.sub(7, 4)
     puts b
     3
    @@ -1937,10 +1922,10 @@ void get_dimensions(Matrix *m, int *rows, int*columns);
    r, c = Example.get_dimensions(m)
    -

    38.6 Exception handling

    +

    34.6 Exception handling

    -

    38.6.1 Using the %exception directive

    +

    34.6.1 Using the %exception directive

    The SWIG %exception directive can be @@ -2049,7 +2034,7 @@ methods and functions named getitem and setitem. limited to C++ exception handling. See the chapter on Customization Features for more examples.

    -

    38.6.2 Handling Ruby Blocks

    +

    34.6.2 Handling Ruby Blocks

    One of the highlights of Ruby and most of its standard library @@ -2086,7 +2071,7 @@ public:

    Then, in ruby, it can be used like:

    -Window.new(0,0,360,480) { |w|
    +Window.new(0, 0, 360, 480) { |w|
       w.color = Fltk::RED
       w.border = false
     }
    @@ -2102,7 +2087,7 @@ a special in typemap, like:

    // // void func(int x); -%typemap(in,numinputs=0) int RUBY_YIELD_SELF { +%typemap(in, numinputs=0) int RUBY_YIELD_SELF { if ( !rb_block_given_p() ) rb_raise("No block given"); return rb_yield(self); @@ -2116,7 +2101,7 @@ a special in typemap, like:

    For more information on typemaps, see Typemaps.

    -

    38.6.3 Raising exceptions

    +

    34.6.3 Raising exceptions

    There are three ways to raise exceptions from C++ code to @@ -2273,7 +2258,7 @@ function. The first argument passed to rb_raise() is the exception type. You can raise a custom exception type or one of the built-in Ruby exception types.

    -

    38.6.4 Exception classes

    +

    34.6.4 Exception classes

    Starting with SWIG 1.3.28, the Ruby module supports the %exceptionclass @@ -2310,7 +2295,7 @@ end

    For another example look at swig/Examples/ruby/exception_class.

    -

    38.7 Typemaps

    +

    34.7 Typemaps

    This section describes how you can modify SWIG's default @@ -2325,7 +2310,7 @@ a required part of using SWIG---the default wrapping behavior is enough in most cases. Typemaps are only used if you want to change some aspect of the primitive C-Ruby interface.

    -

    38.7.1 What is a typemap?

    +

    34.7.1 What is a typemap?

    A typemap is nothing more than a code generation rule that is @@ -2384,7 +2369,7 @@ from Ruby to C, you might define a typemap like this:

    %typemap(in) int { $1 = (int) NUM2INT($input); - printf("Received an integer : %d\n",$1); + printf("Received an integer : %d\n", $1); } %inline %{ @@ -2428,7 +2413,7 @@ supplying an optional parameter name. For example:

    %typemap(in) int n { $1 = (int) NUM2INT($input); - printf("n = %d\n",$1); + printf("n = %d\n", $1); } %inline %{ @@ -2450,7 +2435,7 @@ declarations. For example:

    %typemap(in) int n {
       $1 = (int) NUM2INT($input);
    -  printf("n = %d\n",$1);
    +  printf("n = %d\n", $1);
     }
     
     typedef int Integer;
    @@ -2478,11 +2463,11 @@ always handled as a single Ruby object. This allows the function count
     to be used as follows (notice how the length parameter is omitted): 

    -
    puts Example.count('o','Hello World')
    +
    puts Example.count('o', 'Hello World')
     2
    -

    38.7.2 Typemap scope

    +

    34.7.2 Typemap scope

    Once defined, a typemap remains in effect for all of the @@ -2528,7 +2513,7 @@ where the class itself is defined. For example:

    };
    -

    38.7.3 Copying a typemap

    +

    34.7.3 Copying a typemap

    A typemap is copied by using assignment. For example:

    @@ -2570,7 +2555,7 @@ rules as for %apply (char *buf, int len) { (char *buffer, int size) }; // Multiple arguments
    -

    38.7.4 Deleting a typemap

    +

    34.7.4 Deleting a typemap

    A typemap can be deleted by simply defining no code. For @@ -2595,7 +2580,7 @@ defined by typemaps, clearing a fundamental type like int will make that type unusable unless you also define a new set of typemaps immediately after the clear operation.

    -

    38.7.5 Placement of typemaps

    +

    34.7.5 Placement of typemaps

    Typemap declarations can be declared in the global scope, @@ -2666,13 +2651,13 @@ In this example, this is done using the class declaration class string .

    -

    38.7.6 Ruby typemaps

    +

    34.7.6 Ruby typemaps

    The following list details all of the typemap methods that can be used by the Ruby module:

    -

    38.7.6.1 "in" typemap

    +

    34.7.6.1 "in" typemap

    Converts Ruby objects to input @@ -2739,7 +2724,7 @@ arguments to be specified. For example:

    At this time, only zero or one arguments may be converted.

    -

    38.7.6.2 "typecheck" typemap

    +

    34.7.6.2 "typecheck" typemap

    The "typecheck" typemap is used to support overloaded @@ -2747,7 +2732,7 @@ functions and methods. It merely checks an argument to see whether or not it matches a specific type. For example:

    -
    %typemap(typecheck,precedence=SWIG_TYPECHECK_INTEGER) int {
    +
    %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int {
       $1 = FIXNUM_P($input) ? 1 : 0;
     }
    @@ -2761,7 +2746,7 @@ program uses overloaded methods, you should also define a collection of "typecheck" typemaps. More details about this follow in a later section on "Typemaps and Overloading."

    -

    38.7.6.3 "out" typemap

    +

    34.7.6.3 "out" typemap

    Converts return value of a C function @@ -2812,7 +2797,7 @@ version of the C datatype matched by the typemap. -

    38.7.6.4 "arginit" typemap

    +

    34.7.6.4 "arginit" typemap

    The "arginit" typemap is used to set the initial value of a @@ -2827,7 +2812,7 @@ applications. For example:

    } -

    38.7.6.5 "default" typemap

    +

    34.7.6.5 "default" typemap

    The "default" typemap is used to turn an argument into a @@ -2852,7 +2837,7 @@ arguments that follow must have default values. See the 38.7.6.6 "check" typemap +

    34.7.6.6 "check" typemap

    The "check" typemap is used to supply value checking code @@ -2862,12 +2847,12 @@ arguments have been converted. For example:

    %typemap(check) int positive {
       if ($1 <= 0) {
    -    SWIG_exception(SWIG_ValueError,"Expected positive value.");
    +    SWIG_exception(SWIG_ValueError, "Expected positive value.");
       }
     }
    -

    38.7.6.7 "argout" typemap

    +

    34.7.6.7 "argout" typemap

    The "argout" typemap is used to return values from arguments. @@ -2921,7 +2906,7 @@ some function like SWIG_Ruby_AppendOutput.

    See the typemaps.i library for examples.

    -

    38.7.6.8 "freearg" typemap

    +

    34.7.6.8 "freearg" typemap

    The "freearg" typemap is used to cleanup argument data. It is @@ -2948,7 +2933,7 @@ This code is also placed into a special variable $cleanup that may be used in other typemaps whenever a wrapper function needs to abort prematurely.

    -

    38.7.6.9 "newfree" typemap

    +

    34.7.6.9 "newfree" typemap

    The "newfree" typemap is used in conjunction with the %newobject @@ -2972,7 +2957,7 @@ string *foo();

    See Object ownership and %newobject for further details.

    -

    38.7.6.10 "memberin" typemap

    +

    34.7.6.10 "memberin" typemap

    The "memberin" typemap is used to copy data from an @@ -2990,21 +2975,21 @@ example:

    already provides a default implementation for arrays, strings, and other objects.

    -

    38.7.6.11 "varin" typemap

    +

    34.7.6.11 "varin" typemap

    The "varin" typemap is used to convert objects in the target language to C for the purposes of assigning to a C/C++ global variable. This is implementation specific.

    -

    38.7.6.12 "varout" typemap

    +

    34.7.6.12 "varout" typemap

    The "varout" typemap is used to convert a C/C++ object to an object in the target language when reading a C/C++ global variable. This is implementation specific.

    -

    38.7.6.13 "throws" typemap

    +

    34.7.6.13 "throws" typemap

    The "throws" typemap is only used when SWIG parses a C++ @@ -3045,7 +3030,7 @@ specification yet they do throw exceptions, SWIG cannot know how to deal with them. For a neat way to handle these, see the Exception handling with %exception section.

    -

    38.7.6.14 directorin typemap

    +

    34.7.6.14 directorin typemap

    Converts C++ objects in director @@ -3104,7 +3089,7 @@ referring to the class itself. -

    38.7.6.15 directorout typemap

    +

    34.7.6.15 directorout typemap

    Converts Ruby objects in director @@ -3168,7 +3153,7 @@ directive. Thus, a function can be made to return "nothing" if you do:

    -%feature("numoutputs","0") MyClass::function;
    +%feature("numoutputs", "0") MyClass::function;
     

    This feature can be useful if a function returns a status @@ -3177,7 +3162,7 @@ exception.

    -

    38.7.6.16 directorargout typemap

    +

    34.7.6.16 directorargout typemap

    Output argument processing in director @@ -3235,19 +3220,19 @@ referring to the instance of the class itself -

    38.7.6.17 ret typemap

    +

    34.7.6.17 ret typemap

    Cleanup of function return values

    -

    38.7.6.18 globalin typemap

    +

    34.7.6.18 globalin typemap

    Setting of C global variables

    -

    38.7.7 Typemap variables

    +

    34.7.7 Typemap variables

    @@ -3297,7 +3282,7 @@ so that their values can be properly assigned.

    The Ruby name of the wrapper function being created.
    -

    38.7.8 Useful Functions

    +

    34.7.8 Useful Functions

    When you write a typemap, you usually have to work directly @@ -3312,7 +3297,7 @@ stick to the swig functions instead of the native Ruby functions. That should help you avoid having to rewrite a lot of typemaps across multiple languages.

    -

    38.7.8.1 C Datatypes to Ruby Objects

    +

    34.7.8.1 C Datatypes to Ruby Objects

    @@ -3346,7 +3331,7 @@ across multiple languages.

    rb_float_new(double) - SWIG_From_double(double),
    + SWIG_From_double(double),
    SWIG_From_float(float) float/double to Float @@ -3354,18 +3339,18 @@ SWIG_From_float(float)
    -

    38.7.8.2 Ruby Objects to C Datatypes

    +

    34.7.8.2 Ruby Objects to C Datatypes

    Here, while the Ruby versions return the value directly, the SWIG -versions do not, but return a status value to indicate success (SWIG_OK). While more akward to use, this allows you to write typemaps that report more helpful error messages, like:

    +versions do not, but return a status value to indicate success (SWIG_OK). While more awkward to use, this allows you to write typemaps that report more helpful error messages, like:

     %typemap(in) size_t (int ok)
       ok = SWIG_AsVal_size_t($input, &$1);
       if (!SWIG_IsOK(ok)) {
    -    SWIG_exception_fail(SWIG_ArgError(ok), Ruby_Format_TypeError( "$1_name", "$1_type","$symname", $argnum, $input));
    +    SWIG_exception_fail(SWIG_ArgError(ok), Ruby_Format_TypeError( "$1_name", "$1_type", "$symname", $argnum, $input));
       }
     }
     
    @@ -3422,7 +3407,7 @@ versions do not, but return a status value to indicate success (SWIG_OK
    -

    38.7.8.3 Macros for VALUE

    +

    34.7.8.3 Macros for VALUE

    RSTRING_LEN(str)

    @@ -3445,7 +3430,7 @@ versions do not, but return a status value to indicate success (SWIG_OK
    pointer to array storage
    -

    38.7.8.4 Exceptions

    +

    34.7.8.4 Exceptions

    void rb_raise(VALUE exception, const char *fmt, @@ -3524,7 +3509,7 @@ message to standard error if Ruby was invoked with the -w flag. The given format string fmt and remaining arguments are interpreted as with printf(). -

    38.7.8.5 Iterators

    +

    34.7.8.5 Iterators

    void rb_iter_break()

    @@ -3570,14 +3555,14 @@ VALUE), VALUE value)

    Equivalent to Ruby's throw.
    -

    38.7.9 Typemap Examples

    +

    34.7.9 Typemap Examples

    This section includes a few examples of typemaps. For more examples, you might look at the examples in the Example/ruby directory.

    -

    38.7.10 Converting a Ruby array to a char **

    +

    34.7.10 Converting a Ruby array to a char **

    A common problem in many C programs is the processing of @@ -3615,7 +3600,7 @@ Array instance to be used as a char ** object.

    int print_args(char **argv) { int i = 0; while (argv[i]) { - printf("argv[%d] = %s\n", i,argv[i]); + printf("argv[%d] = %s\n", i, argv[i]); i++; } return i; @@ -3628,7 +3613,7 @@ operates as follows :

    require 'Argv'
    -Argv.print_args(["Dave","Mike","Mary","Jane","John"])
    +Argv.print_args(["Dave", "Mike", "Mary", "Jane", "John"])
     argv[0] = Dave
     argv[1] = Mike
     argv[2] = Mary
    @@ -3642,7 +3627,7 @@ array. Since dynamic memory allocation is used to allocate memory for
     the array, the "freearg" typemap is used to later release this memory
     after the execution of the C function. 

    -

    38.7.11 Collecting arguments in a hash

    +

    34.7.11 Collecting arguments in a hash

    Ruby's solution to the "keyword arguments" capability of some @@ -3719,7 +3704,7 @@ value:

    %typemap(in) (int nattributes, const char **names, const int *values)
       (VALUE keys_arr, int i, VALUE key, VALUE val) {
         Check_Type($input, T_HASH);
    -    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
    +    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
     }
    @@ -3732,7 +3717,7 @@ the keys and values from the hash:

    %typemap(in) (int nattributes, const char **names, const int *values)
       (VALUE keys_arr, int i, VALUE key, VALUE val) {
         Check_Type($input, T_HASH);
    -    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
    +    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
         $2 = NULL;
         $3 = NULL;
         if ($1 > 0) {
    @@ -3751,13 +3736,13 @@ of the keys) and then start looping over the elements in that array: 

    %typemap(in) (int nattributes, const char **names, const int *values)
       (VALUE keys_arr, int i, VALUE key, VALUE val) {
         Check_Type($input, T_HASH);
    -    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
    +    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
         $2 = NULL;
         $3 = NULL;
         if ($1 > 0) {
           $2 = (char **) malloc($1*sizeof(char *));
           $3 = (int *) malloc($1*sizeof(int));
    -      keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
    +      keys_arr = rb_funcall($input, rb_intern("keys"), 0, Qnil);
           for (i = 0; i < $1; i++) {
           }
         }
    @@ -3773,13 +3758,13 @@ corresponding to that key in the hash: 

    %typemap(in) (int nattributes, const char **names, const int *values)
       (VALUE keys_arr, int i, VALUE key, VALUE val) {
         Check_Type($input, T_HASH);
    -    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
    +    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
         $2 = NULL;
         $3 = NULL;
         if ($1 > 0) {
           $2 = (char **) malloc($1*sizeof(char *));
           $3 = (int *) malloc($1*sizeof(int));
    -      keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
    +      keys_arr = rb_funcall($input, rb_intern("keys"), 0, Qnil);
           for (i = 0; i < $1; i++) {
             key = rb_ary_entry(keys_arr, i);
             val = rb_hash_aref($input, key);
    @@ -3796,13 +3781,13 @@ value is a Fixnum: 

    %typemap(in) (int nattributes, const char **names, const int *values)
       (VALUE keys_arr, int i, VALUE key, VALUE val) {
         Check_Type($input, T_HASH);
    -    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
    +    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
         $2 = NULL;
         $3 = NULL;
         if ($1 > 0) {
           $2 = (char **) malloc($1*sizeof(char *));
           $3 = (int *) malloc($1*sizeof(int));
    -      keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
    +      keys_arr = rb_funcall($input, rb_intern("keys"), 0, Qnil);
           for (i = 0; i < $1; i++) {
             key = rb_ary_entry(keys_arr, i);
             val = rb_hash_aref($input, key);
    @@ -3820,13 +3805,13 @@ equivalents and store them in our local C arrays: 

    %typemap(in) (int nattributes, const char **names, const int *values)
       (VALUE keys_arr, int i, VALUE key, VALUE val) {
       Check_Type($input, T_HASH);
    -  $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
    +  $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
       $2 = NULL;
       $3 = NULL;
       if ($1 > 0) {
         $2 = (char **) malloc($1*sizeof(char *));
         $3 = (int *) malloc($1*sizeof(int));
    -    keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
    +    keys_arr = rb_funcall($input, rb_intern("keys"), 0, Qnil);
         for (i = 0; i < $1; i++) {
           key = rb_ary_entry(keys_arr, i);
           val = rb_hash_aref($input, key);
    @@ -3856,7 +3841,7 @@ memory leak. Fortunately, this typemap is a lot easier to write: 

    program that uses the extension, can be found in the Examples/ruby/hashargs directory of the SWIG distribution.

    -

    38.7.12 Pointer handling

    +

    34.7.12 Pointer handling

    Occasionally, it might be necessary to convert pointer values @@ -3915,7 +3900,7 @@ For example:

    }
    -

    38.7.12.1 Ruby Datatype Wrapping

    +

    34.7.12.1 Ruby Datatype Wrapping

    VALUE Data_Wrap_Struct(VALUE class, void @@ -3942,7 +3927,7 @@ as above. type c-type from the data object obj and assigns that pointer to ptr. -

    38.7.13 Example: STL Vector to Ruby Array

    +

    34.7.13 Example: STL Vector to Ruby Array

    Another use for macros and type maps is to create a Ruby array @@ -4034,7 +4019,7 @@ STL with ruby, you are advised to use the standard swig STL library, which does much more than this. Refer to the section called the C++ Standard Template Library. -

    38.8 Docstring Features

    +

    34.8 Docstring Features

    @@ -4068,7 +4053,7 @@ generate ri documentation from a c wrap file, you could do:

    $ rdoc -r file_wrap.c
    -

    38.8.1 Module docstring

    +

    34.8.1 Module docstring

    @@ -4098,7 +4083,7 @@ layout of controls on a panel, etc. to be loaded from an XML file." %module(docstring=DOCSTRING) xrc

    -

    38.8.2 %feature("autodoc")

    +

    34.8.2 %feature("autodoc")

    Since SWIG does know everything about the function it wraps, @@ -4119,7 +4104,7 @@ several options for autodoc controlled by the value given to the feature, described below.

    -

    38.8.2.1 %feature("autodoc", "0")

    +

    34.8.2.1 %feature("autodoc", "0")

    @@ -4143,7 +4128,7 @@ Then Ruby code like this will be generated: ...

    -

    38.8.2.2 %feature("autodoc", "1")

    +

    34.8.2.2 %feature("autodoc", "1")

    @@ -4163,7 +4148,7 @@ this: ...

    -

    38.8.2.3 %feature("autodoc", "2")

    +

    34.8.2.3 %feature("autodoc", "2")

    @@ -4175,7 +4160,7 @@ parameter types with the "2" option will result in Ruby code like this:

    -

    38.8.2.4 %feature("autodoc", "3")

    +

    34.8.2.4 %feature("autodoc", "3")

    @@ -4196,7 +4181,7 @@ Parameters: bar - Bar -

    38.8.2.5 %feature("autodoc", "docstring")

    +

    34.8.2.5 %feature("autodoc", "docstring")

    @@ -4212,7 +4197,7 @@ generated string. For example: void GetPosition(int* OUTPUT, int* OUTPUT); -

    38.8.3 %feature("docstring")

    +

    34.8.3 %feature("docstring")

    @@ -4223,10 +4208,10 @@ docstring associated with classes, function or methods are output. If an item already has an autodoc string then it is combined with the docstring and they are output together.

    -

    38.9 Advanced Topics

    +

    34.9 Advanced Topics

    -

    38.9.1 Operator overloading

    +

    34.9.1 Operator overloading

    SWIG allows operator overloading with, by using the %extend @@ -4407,7 +4392,7 @@ separate method for handling inequality since Ruby parses the expression a != b as !(a == b).

    -

    38.9.2 Creating Multi-Module Packages

    +

    34.9.2 Creating Multi-Module Packages

    The chapter on Working @@ -4533,7 +4518,7 @@ irb(main):005:0> c.getX() 5.0 -

    38.9.3 Specifying Mixin Modules

    +

    34.9.3 Specifying Mixin Modules

    The Ruby language doesn't support multiple inheritance, but @@ -4591,7 +4576,7 @@ comma-separated list of module names to the %mixin directive, e.g.

    -
    %mixin Set "Fee,Fi,Fo,Fum";
    +
    %mixin Set "Fee, Fi, Fo, Fum";

    Note that the %mixin directive is @@ -4600,7 +4585,7 @@ matching rules used for other kinds of features apply (see the chapter on "Customization Features") for more details).

    -

    38.10 Memory Management

    +

    34.10 Memory Management

    One of the most common issues in generating SWIG bindings for @@ -4623,7 +4608,7 @@ to C++ (or vice versa) depending on what function or methods are invoked. Clearly, developing a SWIG wrapper requires a thorough understanding of how the underlying library manages memory.

    -

    38.10.1 Mark and Sweep Garbage Collector

    +

    34.10.1 Mark and Sweep Garbage Collector

    Ruby uses a mark and sweep garbage collector. When the garbage @@ -4654,7 +4639,7 @@ any memory has been allocated in creating the underlying C struct or C++ struct, then a "free" function must be defined that deallocates this memory.

    -

    38.10.2 Object Ownership

    +

    34.10.2 Object Ownership

    As described above, memory management depends on clearly @@ -4799,7 +4784,7 @@ public:

    This code can be seen in swig/examples/ruby/tracking.

    -

    38.10.3 Object Tracking

    +

    34.10.3 Object Tracking

    The remaining parts of this section will use the class library @@ -5025,7 +5010,7 @@ However, if you implement your own free functions (see below) you may also have to call the SWIG_RubyRemoveTracking and RubyUnlinkObjects methods.

    -

    38.10.4 Mark Functions

    +

    34.10.4 Mark Functions

    With a bit more testing, we see that our class library still @@ -5154,7 +5139,7 @@ irb(main):016:0>

    This code can be seen in swig/examples/ruby/mark_function.

    -

    38.10.5 Free Functions

    +

    34.10.5 Free Functions

    By default, SWIG creates a "free" function that is called when @@ -5322,7 +5307,7 @@ been freed, and thus raises a runtime exception.

    This code can be seen in swig/examples/ruby/free_function.

    -

    38.10.6 Embedded Ruby and the C++ Stack

    +

    34.10.6 Embedded Ruby and the C++ Stack

    As has been said, the Ruby GC runs and marks objects before diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index bf1705d20..d1492d30a 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -88,7 +88,7 @@

    This chapter describes the basic operation of SWIG, the structure of its -input files, and how it handles standard ANSI C declarations. C++ support is +input files, and how it handles standard ISO C declarations. C++ support is described in the next chapter. However, C++ programmers should still read this chapter to understand the basics. Specific details about each target language are described in later @@ -103,70 +103,156 @@ To run SWIG, use the swig command with options and a filename like this

    -swig [ options ] filename
    +swig [ options ] filename
     

    where filename is a SWIG interface file or a C/C++ header file. -Below is a subset of options that can be used. +Full help can be seen by running swig -help. +Below is the common set of options that can be used. Additional options are also defined for each target language. A full list -can be obtained by typing swig -help or swig --<lang> -help for language <lang> specific options. +can be obtained by running swig +-<lang> -help for language <lang> specific options, +for example, swig -ruby -help for Ruby.

    --allegrocl            Generate ALLEGROCL wrappers
    --chicken              Generate CHICKEN wrappers
    --clisp                Generate CLISP wrappers
    --cffi                 Generate CFFI wrappers
    --csharp               Generate C# wrappers
    --d                    Generate D wrappers
    --go                   Generate Go wrappers
    --guile                Generate Guile wrappers
    --java                 Generate Java wrappers
    --javascript           Generate Javascript wrappers
    --lua                  Generate Lua wrappers
    --modula3              Generate Modula 3 wrappers
    --mzscheme             Generate Mzscheme wrappers
    --ocaml                Generate Ocaml wrappers
    --octave               Generate Octave wrappers
    --perl                 Generate Perl wrappers
    --php                  Generate PHP wrappers
    --pike                 Generate Pike wrappers
    --python               Generate Python wrappers
    --r                    Generate R (aka GNU S) wrappers
    --ruby                 Generate Ruby wrappers
    --scilab               Generate Scilab wrappers
    --sexp                 Generate Lisp S-Expressions wrappers
    --tcl                  Generate Tcl wrappers
    --uffi                 Generate Common Lisp / UFFI wrappers
    --xml                  Generate XML wrappers
    +Supported Target Language Options
    +     -csharp         - Generate C# wrappers
    +     -d              - Generate D wrappers
    +     -go             - Generate Go wrappers
    +     -guile          - Generate Guile wrappers
    +     -java           - Generate Java wrappers
    +     -javascript     - Generate Javascript wrappers
    +     -lua            - Generate Lua wrappers
    +     -octave         - Generate Octave wrappers
    +     -perl5          - Generate Perl 5 wrappers
    +     -php7           - Generate PHP 7 wrappers
    +     -python         - Generate Python wrappers
    +     -r              - Generate R (aka GNU S) wrappers
    +     -ruby           - Generate Ruby wrappers
    +     -scilab         - Generate Scilab wrappers
    +     -tcl8           - Generate Tcl 8 wrappers
    +     -xml            - Generate XML wrappers
     
    --c++                  Enable C++ parsing
    --cppext ext           Change file extension of C++ generated files to ext
    -                      (default is cxx, except for PHP which uses cpp)
    --Dsymbol              Define a preprocessor symbol
    --Fstandard            Display error/warning messages in commonly used format
    --Fmicrosoft           Display error/warning messages in Microsoft format
    --help                 Display all options
    --Idir                 Add a directory to the file include path
    --lfile                Include a SWIG library file.
    --module name          Set the name of the SWIG module
    --o outfile            Set name of C/C++ output file to <outfile>
    --oh headfile          Set name of C++ output header file for directors to <headfile>
    --outcurrentdir        Set default output dir to current dir instead of input file's path
    --outdir dir           Set language specific files output directory
    --pcreversion          Display PCRE version information
    --swiglib              Show location of SWIG library
    --version              Show SWIG version number
    +Experimental Target Language Options
    +     -mzscheme       - Generate MzScheme/Racket wrappers
    +     -ocaml          - Generate OCaml wrappers
     
    +General Options
    +     -addextern      - Add extra extern declarations
    +     -c++            - Enable C++ processing
    +     -co <file>      - Check <file> out of the SWIG library
    +     -copyctor       - Automatically generate copy constructors wherever possible
    +     -cpperraswarn   - Treat the preprocessor #error statement as #warning (default)
    +     -cppext <ext>   - Change file extension of generated C++ files to <ext>
    +                       (default is cxx)
    +     -copyright      - Display copyright notices
    +     -debug-classes  - Display information about the classes found in the interface
    +     -debug-module <n>- Display module parse tree at stages 1-4, <n> is a csv list of stages
    +     -debug-symtabs  - Display symbol tables information
    +     -debug-symbols  - Display target language symbols in the symbol tables
    +     -debug-csymbols - Display C symbols in the symbol tables
    +     -debug-lsymbols - Display target language layer symbols
    +     -debug-tags     - Display information about the tags found in the interface
    +     -debug-template - Display information for debugging templates
    +     -debug-top <n>  - Display entire parse tree at stages 1-4, <n> is a csv list of stages
    +     -debug-typedef  - Display information about the types and typedefs in the interface
    +     -debug-typemap  - Display typemap debugging information
    +     -debug-tmsearch - Display typemap search debugging information
    +     -debug-tmused   - Display typemaps used debugging information
    +     -directors      - Turn on director mode for all the classes, mainly for testing
    +     -dirprot        - Turn on wrapping of protected members for director classes (default)
    +     -D<symbol>      - Define a symbol <symbol> (for conditional compilation)
    +     -E              - Preprocess only, does not generate wrapper code
    +     -external-runtime [file] - Export the SWIG runtime stack
    +     -fakeversion <v>- Make SWIG fake the program version number to <v>
    +     -fcompact       - Compile in compact mode
    +     -features <list>- Set global features, where <list> is a comma separated list of
    +                       features, eg -features directors,autodoc=1
    +                       If no explicit value is given to the feature, a default of 1 is used
    +     -fastdispatch   - Enable fast dispatch mode to produce faster overload dispatcher code
    +     -Fmicrosoft     - Display error/warning messages in Microsoft format
    +     -Fstandard      - Display error/warning messages in commonly used format
    +     -fvirtual       - Compile in virtual elimination mode
    +     -help           - Display help
    +     -I-             - Don't search the current directory
    +     -I<dir>         - Look for SWIG files in directory <dir>
    +     -ignoremissing  - Ignore missing include files
    +     -importall      - Follow all #include statements as imports
    +     -includeall     - Follow all #include statements
    +     -l<ifile>       - Include SWIG library file <ifile>
    +     -macroerrors    - Report errors inside macros
    +     -makedefault    - Create default constructors/destructors (the default)
    +     -M              - List all dependencies
    +     -MD             - Is equivalent to `-M -MF <file>', except `-E' is not implied
    +     -MF <file>      - Generate dependencies into <file> and continue generating wrappers
    +     -MM             - List dependencies, but omit files in SWIG library
    +     -MMD            - Like `-MD', but omit files in SWIG library
    +     -module <name>  - Set module name to <name>
    +     -MP             - Generate phony targets for all dependencies
    +     -MT <target>    - Set the target of the rule emitted by dependency generation
    +     -nocontract     - Turn off contract checking
    +     -nocpperraswarn - Do not treat the preprocessor #error statement as #warning
    +     -nodefault      - Do not generate default constructors nor default destructors
    +     -nodefaultctor  - Do not generate implicit default constructors
    +     -nodefaultdtor  - Do not generate implicit default destructors
    +     -nodirprot      - Do not wrap director protected members
    +     -noexcept       - Do not wrap exception specifiers
    +     -nofastdispatch - Disable fast dispatch mode (default)
    +     -nopreprocess   - Skip the preprocessor step
    +     -notemplatereduce - Disable reduction of the typedefs in templates
    +     -O              - Enable the optimization options:
    +                        -fastdispatch -fvirtual
    +     -o <outfile>    - Set name of C/C++ output file to <outfile>
    +     -oh <headfile>  - Set name of C++ output header file for directors to <headfile>
    +     -outcurrentdir  - Set default output dir to current dir instead of input file's path
    +     -outdir <dir>   - Set language specific files output directory to <dir>
    +     -pcreversion    - Display PCRE version information
    +     -small          - Compile in virtual elimination and compact mode
    +     -swiglib        - Report location of SWIG library and exit
    +     -templatereduce - Reduce all the typedefs in templates
    +     -v              - Run in verbose mode
    +     -version        - Display SWIG version number
    +     -Wall           - Remove all warning suppression, also implies -Wextra
    +     -Wallkw         - Enable keyword warnings for all the supported languages
    +     -Werror         - Treat warnings as errors
    +     -Wextra         - Adds the following additional warnings: 202,309,403,405,512,321,322
    +     -w<list>        - Suppress/add warning messages, eg -w401,+321 - see Warnings.html
    +     -xmlout <file>  - Write XML version of the parse tree to <file> after normal processing
     
    +

    +Arguments may also be passed in a command-line options file (also known as a +response file) which is useful if they exceed the system command line length +limit. To do this, put the arguments in a file, then provide the file name +prefixed with @ like so: +

    + +
    +swig @file
    +
    + +

    +The options read from the file are inserted in place of the file option. If the +file does not exist, or cannot be read, then the option will be treated +literally and not removed. +

    + +

    +Options in the file are separated by whitespace. A whitespace character may be +included in an option by surrounding the entire option in either single or +double quotes. Any character (including a backslash) may be included by +prefixing the character to be included with a backslash. The file may itself +contain additional @file options; any such options will be processed +recursively. +

    +

    5.1.1 Input format

    -As input, SWIG expects a file containing ANSI C/C++ declarations and +As input, SWIG expects a file containing ISO C/C++ declarations and special SWIG directives. More often than not, this is a special SWIG interface file which is usually denoted with a special .i or .swg suffix. In certain cases, SWIG can be used directly on @@ -184,7 +270,7 @@ The most common format of a SWIG interface is as follows: %{ #include "myheader.h" %} -// Now list ANSI C/C++ declarations +// Now list ISO C/C++ declarations int foo; int bar(int x); ... @@ -388,7 +474,7 @@ For example /* bar not wrapped unless foo has been defined and the declaration of bar within foo has already been parsed */ int foo::bar(int) { - ... whatever ... + ... whatever ... } @@ -479,7 +565,7 @@ Or in Python:

     >>> example.sin(3)
     5.2335956
    ->>> example.strcmp('Dave','Mike')
    +>>> example.strcmp('Dave', 'Mike')
     -1
     >>> print example.cvar.Foo
     42
    @@ -648,7 +734,7 @@ print cvar.foo                  # Print value of foo
     
     # Perl
     $foo = 3.5;                     # Set foo to 3.5
    -print $foo,"\n";                # Print value of foo
    +print $foo, "\n";               # Print value of foo
     
     # Ruby
     Module.foo = 3.5               # Set foo to 3.5
    @@ -749,7 +835,7 @@ form of type-checking however).

    For enumerations, it is critical that the original enum definition be included somewhere in the interface file (either in a header file or -in the %{,%} block). SWIG only translates the enumeration +in the %{ %} block). SWIG only translates the enumeration into code needed to add the constants to a scripting language. It needs the original enumeration declaration in order to get the correct enum values as assigned by the C compiler. @@ -1041,15 +1127,15 @@ expect :

     # Copy a file 
    -def filecopy(source,target):
    -  f1 = fopen(source,"r")
    -  f2 = fopen(target,"w")
    -  buffer = malloc(8192)
    -  nbytes = fread(buffer,8192,1,f1)
    -  while (nbytes > 0):
    -    fwrite(buffer,8192,1,f2)
    -          nbytes = fread(buffer,8192,1,f1)
    -  free(buffer)
    +def filecopy(source, target):
    +    f1 = fopen(source, "r")
    +    f2 = fopen(target, "w")
    +    buffer = malloc(8192)
    +    nbytes = fread(buffer, 8192, 1, f1)
    +    while (nbytes > 0):
    +        fwrite(buffer, 8192, 1, f2)
    +            nbytes = fread(buffer, 8192, 1, f1)
    +    free(buffer)
     

    @@ -1235,9 +1321,9 @@ creating a wrapper equivalent to the following:

     double wrap_dot_product(Vector *a, Vector *b) {
    -    Vector x = *a;
    -    Vector y = *b;
    -    return dot_product(x,y);
    +  Vector x = *a;
    +  Vector y = *b;
    +  return dot_product(x, y);
     }
     
    @@ -1265,12 +1351,12 @@ pointers. As a result, SWIG creates a wrapper like this:
     Vector *wrap_cross_product(Vector *v1, Vector *v2) {
    -        Vector x = *v1;
    -        Vector y = *v2;
    -        Vector *result;
    -        result = (Vector *) malloc(sizeof(Vector));
    -        *(result) = cross(x,y);
    -        return result;
    +  Vector x = *v1;
    +  Vector y = *v2;
    +  Vector *result;
    +  result = (Vector *) malloc(sizeof(Vector));
    +  *(result) = cross(x, y);
    +  return result;
     }
     
    @@ -1279,10 +1365,10 @@ or if SWIG was run with the -c++ option:

     Vector *wrap_cross(Vector *v1, Vector *v2) {
    -        Vector x = *v1;
    -        Vector y = *v2;
    -        Vector *result = new Vector(cross(x,y)); // Uses default copy constructor
    -        return result;
    +  Vector x = *v1;
    +  Vector y = *v2;
    +  Vector *result = new Vector(cross(x, y)); // Uses default copy constructor
    +  return result;
     }
     
    @@ -1357,16 +1443,16 @@ SWIG generates the following code:
     /* C mode */
     void foo_set(char *value) {
    -   if (foo) free(foo);
    -   foo = (char *) malloc(strlen(value)+1);
    -   strcpy(foo,value);
    +  if (foo) free(foo);
    +  foo = (char *) malloc(strlen(value)+1);
    +  strcpy(foo, value);
     }
     
     /* C++ mode.  When -c++ option is used */
     void foo_set(char *value) {
    -   if (foo) delete [] foo;
    -   foo = new char[strlen(value)+1];
    -   strcpy(foo,value);
    +  if (foo) delete [] foo;
    +  foo = new char[strlen(value)+1];
    +  strcpy(foo, value);
     }
     
    @@ -1381,8 +1467,8 @@ exactly like you want. For example:
     %inline %{
       void set_foo(char *value) {
    -       strncpy(foo,value, 50);
    -   }
    +    strncpy(foo, value, 50);
    +  }
     %}
     
    @@ -1538,10 +1624,10 @@ a few simple assist functions like this:
     %inline %{
     void a_set(int i, int j, int val) {
    -   a[i][j] = val;
    +  a[i][j] = val;
     }
     int a_get(int i, int j) {
    -   return a[i][j];
    +  return a[i][j];
     }
     %}
     
    @@ -1558,11 +1644,11 @@ some helper functions in your interface. For example: %inline %{ /* Create any sort of [size] array */ int *int_array(int size) { - return (int *) malloc(size*sizeof(int)); + return (int *) malloc(size*sizeof(int)); } /* Create a two-dimension array [size][10] */ int (*int_array_10(int size))[10] { - return (int (*)[10]) malloc(size*10*sizeof(int)); + return (int (*)[10]) malloc(size*10*sizeof(int)); } %} @@ -1587,10 +1673,10 @@ code:
     char *pathname_get() {
    -   return pathname;
    +  return pathname;
     }
     void pathname_set(char *value) {
    -   strncpy(pathname,value,256);
    +  strncpy(pathname, value, 256);
     }
     
    @@ -1611,9 +1697,9 @@ directive as shown :

    int a; // Can read/write %immutable; -int b,c,d; // Read only variables +int b, c, d; // Read only variables %mutable; -double x,y; // read/write +double x, y; // read/write

    @@ -1638,7 +1724,7 @@ The %mutable and %immutable directives are actually

     #define %immutable   %feature("immutable")
    -#define %mutable     %feature("immutable","")
    +#define %mutable     %feature("immutable", "")
     

    @@ -1647,7 +1733,7 @@ If you wanted to make all wrapped variables read-only, barring one or two, it mi

     %immutable;                     // Make all variables read-only
    -%feature("immutable","0") x;    // except, make x read/write
    +%feature("immutable", "0") x;   // except, make x read/write
     ...
     double x;
     double y;
    @@ -1735,6 +1821,16 @@ already defined in the target scripting language. However, if you are
     careful about namespaces and your use of modules, you can usually
     avoid these problems.

    +

    +When wrapping C code, simple use of identifiers/symbols with %rename usually suffices. +When wrapping C++ code, simple use of simple identifiers/symbols with %rename might be too +limiting when using C++ features such as function overloading, default arguments, namespaces, template specialization etc. +If you are using the %rename directive and C++, make sure you read the +SWIG and C++ chapter and in particular the section on +Renaming and ambiguity resolution +for method overloading and default arguments. +

    +

    Closely related to %rename is the %ignore directive. %ignore instructs SWIG to ignore declarations that match a given identifier. For example: @@ -2077,7 +2173,7 @@ except those consisting of capital letters only:

    Finally, variants of %rename and %ignore directives can be used to help wrap C++ overloaded functions and methods or C++ methods which use default arguments. This is described in the -Ambiguity resolution and renaming section in the C++ chapter. +Renaming and ambiguity resolution section in the C++ chapter.

    @@ -2146,7 +2242,7 @@ used in Tcl as follows :

    -Although the ANSI C standard does not allow default arguments, default +Although the ISO C standard does not allow default arguments, default arguments specified in a SWIG interface work with both C and C++.

    @@ -2166,13 +2262,13 @@ in the C++ chapter for further details.

    Occasionally, a C library may include functions that expect to receive pointers to functions--possibly to serve as callbacks. SWIG -provides full support for function pointers provided that the callback +provides full support for function pointers when the callback functions are defined in C and not in the target language. For example, consider a function like this:

    -int binary_op(int a, int b, int (*op)(int,int));
    +int binary_op(int a, int b, int (*op)(int, int));
     

    @@ -2181,10 +2277,10 @@ may find the function to be impossible to use. For instance, in Python:

    ->>> def add(x,y):
    +>>> def add(x, y):
     ...     return x+y
     ...
    ->>> binary_op(3,4,add)
    +>>> binary_op(3, 4, add)
     Traceback (most recent call last):
       File "<stdin>", line 1, in ?
     TypeError: Type error. Expected _p_f_int_int__int
    @@ -2201,12 +2297,12 @@ One way to do this is to use the %constant directive like this:
     
     
     /* Function with a callback */
    -int binary_op(int a, int b, int (*op)(int,int));
    +int binary_op(int a, int b, int (*op)(int, int));
     
     /* Some callback functions */
    -%constant int add(int,int);
    -%constant int sub(int,int);
    -%constant int mul(int,int);
    +%constant int add(int, int);
    +%constant int sub(int, int);
    +%constant int mul(int, int);
     

    @@ -2216,9 +2312,9 @@ constants in the target scripting language. This allows you to use them as foll

    ->>> binary_op(3,4,add)
    +>>> binary_op(3, 4, add)
     7
    ->>> binary_op(3,4,mul)
    +>>> binary_op(3, 4, mul)
     12
     >>>
     
    @@ -2231,7 +2327,7 @@ as functions. For example:
    ->>> add(3,4)
    +>>> add(3, 4)
     Traceback (most recent call last):
       File "<stdin>", line 1, in ?
     TypeError: object is not callable: '_ff020efc_p_f_int_int__int'
    @@ -2247,13 +2343,13 @@ can use the %callback and %nocallback directives like this:
     
     /* Function with a callback */
    -int binary_op(int a, int b, int (*op)(int,int));
    +int binary_op(int a, int b, int (*op)(int, int));
     
     /* Some callback functions */
     %callback("%s_cb");
    -int add(int,int);
    -int sub(int,int);
    -int mul(int,int);
    +int add(int, int);
    +int sub(int, int);
    +int mul(int, int);
     %nocallback;
     
    @@ -2266,13 +2362,13 @@ disabled using %nocallback. When you do this, the interface now works
    ->>> binary_op(3,4,add_cb)
    +>>> binary_op(3, 4, add_cb)
     7
    ->>> binary_op(3,4,mul_cb)
    +>>> binary_op(3, 4, mul_cb)
     12
    ->>> add(3,4)
    +>>> add(3, 4)
     7
    ->>> mul(3,4)
    +>>> mul(3, 4)
     12
     
    @@ -2293,9 +2389,9 @@ variation installs the callbacks as all upper case constants such as
     /* Some callback functions */
     %callback("%(uppercase)s");
    -int add(int,int);
    -int sub(int,int);
    -int mul(int,int);
    +int add(int, int);
    +int sub(int, int);
    +int mul(int, int);
     %nocallback;
     
    @@ -2310,14 +2406,16 @@ And now, a final note about function pointer support. Although SWIG does not normally allow callback functions to be written in the target language, this can be accomplished with the use of typemaps and other advanced SWIG features. See the Typemaps chapter for more about typemaps -and individual target language chapters for more on callbacks and the 'director' feature. +and individual target language chapters for more on callbacks. +The 'director' feature can be used to make callbacks from C/C++ into the target language, +see Callbacks to the target language.

    5.5 Structures and unions

    -This section describes the behavior of SWIG when processing ANSI C structures and union declarations. Extensions to +This section describes the behavior of SWIG when processing ISO C structures and union declarations. Extensions to handle C++ are described in the next section.

    @@ -2331,7 +2429,7 @@ to an individual member. For example, the declaration :

     struct Vector {
    -  double x,y,z;
    +  double x, y, z;
     }
     
     
    @@ -2367,10 +2465,10 @@ defined in the interface. For example:
     struct Vector *new_Vector() {
    -    return (Vector *) calloc(1,sizeof(struct Vector));
    +  return (Vector *) calloc(1, sizeof(struct Vector));
     }
     void delete_Vector(struct Vector *obj) {
    -    free(obj);
    +  free(obj);
     }
     
    @@ -2383,9 +2481,9 @@ language using code like this:
     v = new_Vector()
    -Vector_x_set(v,2)
    -Vector_y_set(v,10)
    -Vector_z_set(v,-5)
    +Vector_x_set(v, 2)
    +Vector_y_set(v, 10)
    +Vector_z_set(v, -5)
     ...
     delete_Vector(v)
     
    @@ -2404,7 +2502,7 @@ programs :

     typedef struct {
    -  double x,y,z;
    +  double x, y, z;
     } Vector;
     
     
    @@ -2429,7 +2527,7 @@ If two different names are used like this :

     typedef struct vector_struct {
    -  double x,y,z;
    +  double x, y, z;
     } Vector;
     
     
    @@ -2473,7 +2571,7 @@ char *Foo_name_set(Foo *obj, char *c) { if (obj->name) free(obj->name); obj->name = (char *) malloc(strlen(c)+1); - strcpy(obj->name,c); + strcpy(obj->name, c); return obj->name; }
    @@ -2521,12 +2619,12 @@ Occasionally, a structure will contain data members that are themselves structur
     typedef struct Foo {
    -   int x;
    +  int x;
     } Foo;
     
     typedef struct Bar {
    -   int y;
    -   Foo f;           /* struct member */
    +  int y;
    +  Foo f;           /* struct member */
     } Bar;
     
    @@ -2540,10 +2638,10 @@ The accessors to the member variable as a pointer are effectively wrapped as fol
     Foo *Bar_f_get(Bar *b) {
    -   return &b->f;
    +  return &b->f;
     }
     void Bar_f_set(Bar *b, Foo *value) {
    -   b->f = *value;
    +  b->f = *value;
     }
     
    @@ -2570,7 +2668,7 @@ language interface) results in the following code:
     Bar *b;
    -Foo_x_set(Bar_f_get(b),37);
    +Foo_x_set(Bar_f_get(b), 37);
     
    @@ -2588,7 +2686,7 @@ is a structure or class. For instance, if you had a structure like this,
     struct Foo {
    -   WORD   w;
    +  WORD   w;
     };
     
    @@ -2601,10 +2699,10 @@ like this:
     WORD Foo_w_get(Foo *f) {
    -    return f->w;
    +  return f->w;
     }
     void Foo_w_set(FOO *f, WORD value) {
    -    f->w = value;
    +  f->w = value;
     }
     
    @@ -2726,7 +2824,7 @@ the following declaration :

    /* file : vector.h */ ... typedef struct Vector { - double x,y,z; + double x, y, z; } Vector;
    @@ -2759,7 +2857,7 @@ You can make a Vector look a lot like a class by writing a SWIG interfa return sqrt($self->x*$self->x+$self->y*$self->y+$self->z*$self->z); } void print() { - printf("Vector [%g, %g, %g]\n", $self->x,$self->y,$self->z); + printf("Vector [%g, %g, %g]\n", $self->x, $self->y, $self->z); } }; @@ -2779,7 +2877,7 @@ Now, when used with proxy classes in Python, you can do things like this :

    ->>> v = Vector(3,4,0)                 # Create a new vector
    +>>> v = Vector(3, 4, 0)                 # Create a new vector
     >>> print v.magnitude()                # Print magnitude
     5.0
     >>> v.print()                  # Print it out
    @@ -2799,7 +2897,7 @@ of the Vector structure. For example:

    %} typedef struct Vector { - double x,y,z; + double x, y, z; %extend { Vector(double x, double y, double z) { ... } ~Vector() { ... } @@ -2841,12 +2939,12 @@ double Vector_magnitude(Vector *v) { %} typedef struct Vector { - double x,y,z; + double x, y, z; %extend { - Vector(int,int,int); // This calls new_Vector() - ~Vector(); // This calls delete_Vector() - double magnitude(); // This will call Vector_magnitude() - ... + Vector(int, int, int); // This calls new_Vector() + ~Vector(); // This calls delete_Vector() + double magnitude(); // This will call Vector_magnitude() + ... } } Vector;
    @@ -2895,7 +2993,7 @@ instead of a method. To do this, you might write some code like this:
     // Add a new attribute to Vector
     %extend Vector {
    -    const double magnitude;
    +  const double magnitude;
     }
     // Now supply the implementation of the Vector_magnitude_get function
     %{
    @@ -2958,7 +3056,7 @@ char *Person_name_get(Person *p) {
     }
     
     void Person_name_set(Person *p, char *val) {
    -  strncpy(p->name,val,50);
    +  strncpy(p->name, val, 50);
       make_upper(p->name);
     }
     %}
    @@ -3083,7 +3181,7 @@ in terms of high-level accessor functions such as this,
     
     double Vector_x_get(Vector *v) {
    -   return v->x;
    +  return v->x;
     }
     
    @@ -3100,15 +3198,15 @@ the following function is generated instead: static int _wrap_Vector_x_get(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - struct Vector *arg1 ; - double result ; - - if (SWIG_GetArgs(interp, objc, objv,"p:Vector_x_get self ",&arg0, - SWIGTYPE_p_Vector) == TCL_ERROR) - return TCL_ERROR; - result = (double ) (arg1->x); - Tcl_SetObjResult(interp,Tcl_NewDoubleObj((double) result)); - return TCL_OK; + struct Vector *arg1 ; + double result ; + + if (SWIG_GetArgs(interp, objc, objv, "p:Vector_x_get self ", &arg0, + SWIGTYPE_p_Vector) == TCL_ERROR) + return TCL_ERROR; + result = (double ) (arg1->x); + Tcl_SetObjResult(interp, Tcl_NewDoubleObj((double) result)); + return TCL_OK; }
    @@ -3139,9 +3237,9 @@ output of SWIG is structured first.

    -When SWIG creates its output file, it is broken up into five sections +When SWIG creates its output C/C++ file, it is broken up into five sections corresponding to runtime code, headers, wrapper functions, and module -initialization code (in that order). +initialization code (in that order).

      @@ -3175,31 +3273,59 @@ the module upon loading.

      -Code is inserted into the appropriate code section by using one -of the code insertion directives listed below. The order of the sections in -the wrapper file is as shown: +The %insert directive enables inserting blocks of code into a given section of the generated code. +It can be used in one of two ways: +

      + +
      +
      +%insert("section") "filename"
      +%insert("section") %{ ... %}
      +
      +
      + +

      +The first will dump the contents of the file in the given filename into the named section. +The second inserts the code between the braces into the named section. +For example, the following adds code into the runtime section: +

      + +
      +
      +%insert("runtime") %{
      +  ... code in runtime section ...
      +%}
      +
      +
      + +

      +There are the 5 sections, however, some target languages add in additional sections and some of these result in code being generated into a target language file instead of the C/C++ wrapper file. +These are documented when available in the target language chapters. +Macros named after the code sections are available as additional directives and these macro directives are normally used instead of %insert. +For example, %runtime is used instead of %insert("runtime"). +The valid sections and order of the sections in the generated C/C++ wrapper file is as shown:

       %begin %{
      -   ... code in begin section ...
      +  ... code in begin section ...
       %}
       
       %runtime %{
      -   ... code in runtime section ...
      +  ... code in runtime section ...
       %}
       
       %header %{
      -   ... code in header section ...
      +  ... code in header section ...
       %}
       
       %wrapper %{
      -   ... code in wrapper section ...
      +  ... code in wrapper section ...
       %}
       
       %init %{
      -   ... code in init section ...
      +  ... code in init section ...
       %}
       
      @@ -3264,11 +3390,27 @@ Vector *new_Vector() { return (Vector *) malloc(sizeof(Vector)); } %} -

      -The %inline directive inserts all of the code that follows +This is the same as writing: +

      + +
      +%{
      +/* Create a new vector */
      +Vector *new_Vector() {
      +  return (Vector *) malloc(sizeof(Vector));
      +}
      +%}
      +
      +/* Create a new vector */
      +Vector *new_Vector() {
      +  return (Vector *) malloc(sizeof(Vector));
      +}
      +
      +

      +In other words, the %inline directive inserts all of the code that follows verbatim into the header portion of an interface file. The code is then parsed by both the SWIG preprocessor and parser. Thus, the above example creates a new command new_Vector using only one @@ -3276,6 +3418,11 @@ declaration. Since the code inside an %inline %{ ... %} block is given to both the C compiler and SWIG, it is illegal to include any SWIG directives inside a %{ ... %} block.

      + +

      +Note: The usual SWIG C preprocessor rules apply to code in %apply blocks when SWIG parses this code. For example, as mentioned earlier, SWIG's C Preprocessor does not follow #include directives by default. +

      +

      5.6.4 Initialization blocks

      @@ -3322,7 +3469,7 @@ interface to your program. SWIG's %include directive to process an entire C source/header file. -
    • Make sure everything in the interface file uses ANSI C/C++ syntax. +
    • Make sure everything in the interface file uses ISO C/C++ syntax.
    • Make sure all necessary `typedef' declarations and type-information is available in the interface file. @@ -3441,7 +3588,7 @@ header files.

      Sometimes, it is necessary to use certain header files in order for the code generated by SWIG to compile properly. Make sure you -include certain header files by using a %{,%} block like this: +include certain header files by using a %{ %} block like this:

      diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html
      index 73b242fa3..dc9ae0f7e 100644
      --- a/Doc/Manual/SWIGPlus.html
      +++ b/Doc/Manual/SWIGPlus.html
      @@ -31,7 +31,6 @@
       
    • Static members
    • Member data
    -
  • Default arguments
  • Protection
  • Enums and constants
  • Friends @@ -39,16 +38,27 @@
  • Pass and return by value
  • Inheritance
  • A brief discussion of multiple inheritance, pointers, and type checking -
  • Wrapping Overloaded Functions and Methods +
  • Default arguments +
  • Overloaded functions and methods -
  • Wrapping overloaded operators +
  • Overloaded operators
  • Class extension
  • Templates +
  • Namespaces @@ -70,9 +85,15 @@

    -This chapter describes SWIG's support for wrapping C++. As a prerequisite, +This chapter describes SWIG's support for wrapping C++. +It is mostly concerned about C++ as defined by the C++ 98 and 03 standards. +For additions to the original C++ standard, please read the +SWIG and C++11, +SWIG and C++14 and +SWIG and C++17 chapters. +As a prerequisite, you should first read the chapter SWIG Basics to see -how SWIG wraps ANSI C. Support for C++ builds upon ANSI C +how SWIG wraps ISO C. Support for C++ builds upon ISO C wrapping and that material will be useful in understanding this chapter.

    @@ -123,7 +144,7 @@ yourself in the foot. You will just have to be careful.

    To wrap C++, SWIG uses a layered approach to code generation. -At the lowest level, SWIG generates a collection of procedural ANSI-C style +At the lowest level, SWIG generates a collection of procedural ISO C style wrappers. These wrappers take care of basic type conversion, type checking, error handling, and other low-level details of the C++ binding. These wrappers are also sufficient to bind C++ into any target language @@ -256,11 +277,11 @@ C++ class like this:

     class Foo {
    -public:
    -      Foo();
    -     ~Foo();
    -      int  bar(int x);
    -      int  x;
    +  public:
    +    Foo();
    +    ~Foo();
    +    int  bar(int x);
    +    int  x;
     };
     
    @@ -272,24 +293,24 @@ Using C++ as pseudocode, a proxy class looks something like this:
     class FooProxy {
    -private:
    -      Foo    *self;
    -public:
    -      FooProxy() {
    -            self = new_Foo();
    -      }
    -     ~FooProxy() {
    -            delete_Foo(self);
    -      }
    -      int bar(int x) {
    -            return Foo_bar(self,x);
    -      }
    -      int x_get() {
    -            return Foo_x_get(self);
    -      }
    -      void x_set(int x) {
    -            Foo_x_set(self,x);
    -      }
    +  private:
    +    Foo    *self;
    +  public:
    +    FooProxy() {
    +      self = new_Foo();
    +    }
    +    ~FooProxy() {
    +      delete_Foo(self);
    +    }
    +    int bar(int x) {
    +      return Foo_bar(self, x);
    +    }
    +    int x_get() {
    +      return Foo_x_get(self);
    +    }
    +    void x_set(int x) {
    +      Foo_x_set(self, x);
    +    }
     };
     
    @@ -303,19 +324,19 @@ For example, in Python, the proxy might look roughly like this:
     class Foo:
         def __init__(self):
    -         self.this = new_Foo()
    +        self.this = new_Foo()
         def __del__(self):
    -         delete_Foo(self.this)
    -    def bar(self,x):
    -         return Foo_bar(self.this,x)
    -    def __getattr__(self,name):
    -         if name == 'x':
    -              return Foo_x_get(self.this)
    -         ...
    -    def __setattr__(self,name,value):
    -         if name == 'x':
    -              Foo_x_set(self.this,value)
    -         ...
    +        delete_Foo(self.this)
    +    def bar(self, x):
    +        return Foo_bar(self.this, x)
    +    def __getattr__(self, name):
    +        if name == 'x':
    +            return Foo_x_get(self.this)
    +        ...
    +    def __setattr__(self, name, value):
    +        if name == 'x':
    +            Foo_x_set(self.this, value)
    +        ...
     
    @@ -338,16 +359,16 @@ C++ code:
     class Foo {
     public:
    -      Foo();
    -     ~Foo();
    -      int bar(int x);
    -      int x;
    +  Foo();
    +  ~Foo();
    +  int bar(int x);
    +  int x;
     };
     
     class Spam {
     public:
    -      Foo *value;
    -      ...
    +  Foo *value;
    +  ...
     };
     
    @@ -407,45 +428,45 @@ roughly like this:
     class FooProxy {
    -public:
    -      Foo    *self;
    -      int     thisown;
    +  public:
    +    Foo    *self;
    +    int     thisown;
     
    -      FooProxy() {
    -            self = new_Foo();
    -            thisown = 1;       // Newly created object
    -      }
    -     ~FooProxy() {
    -            if (thisown) delete_Foo(self);
    -      }
    -      ...
    -      // Ownership control API
    -      void disown() {
    -           thisown = 0;
    -      }
    -      void acquire() {
    -           thisown = 1;
    -      }
    +    FooProxy() {
    +      self = new_Foo();
    +      thisown = 1;       // Newly created object
    +    }
    +    ~FooProxy() {
    +      if (thisown) delete_Foo(self);
    +    }
    +    ...
    +    // Ownership control API
    +    void disown() {
    +      thisown = 0;
    +    }
    +    void acquire() {
    +      thisown = 1;
    +    }
     };
     
     class FooPtrProxy: public FooProxy {
     public:
    -      FooPtrProxy(Foo *s) {
    -          self = s;
    -          thisown = 0;
    -      }
    +  FooPtrProxy(Foo *s) {
    +    self = s;
    +    thisown = 0;
    +  }
     };
     
     class SpamProxy {
    -     ...
    -     FooProxy *value_get() {
    -          return FooPtrProxy(Spam_value_get(self));
    -     }
    -     void value_set(FooProxy *v) {
    -          Spam_value_set(self,v->self);
    -          v->disown();
    -     }
    -     ...
    +  ...
    +  FooProxy *value_get() {
    +    return FooPtrProxy(Spam_value_get(self));
    +  }
    +  void value_set(FooProxy *v) {
    +    Spam_value_set(self, v->self);
    +    v->disown();
    +  }
    +  ...
     };
     
    @@ -704,9 +725,9 @@ First, SWIG won't generate wrappers for protected or private constructors. For
     class Foo {
     protected:
    -     Foo();         // Not wrapped.
    +  Foo();         // Not wrapped.
     public:
    -      ...
    +  ...
     };
     
    @@ -720,13 +741,13 @@ pure virtual methods. Here are some examples:
     class Bar {
     public:
    -     Bar();               // Not wrapped.  Bar is abstract.
    -     virtual void spam(void) = 0; 
    +  Bar();               // Not wrapped.  Bar is abstract.
    +  virtual void spam(void) = 0;
     };
     
     class Grok : public Bar {
     public:
    -      Grok();            // Not wrapped. No implementation of abstract spam().
    +  Grok();              // Not wrapped. No implementation of abstract spam().
     };
     
    @@ -754,8 +775,8 @@ non-abstract using this: class Foo : public Bar { public: - Foo(); // Generated no matter what---not abstract. - ... + Foo(); // Generated no matter what---not abstract. + ... }; @@ -777,9 +798,9 @@ the normal constructor function. For example, if you have this:
     class List {
     public:
    -    List();    
    -    List(const List &);      // Copy constructor
    -    ...
    +  List();    
    +  List(const List &);      // Copy constructor
    +  ...
     };
     
    @@ -803,7 +824,7 @@ through a special function like this:
     List *copy_List(List *f) {
    -    return new List(*f);
    +  return new List(*f);
     }
     
    @@ -832,7 +853,7 @@ However, copy constructor wrappers can be generated if using the copyctor @@ -851,9 +872,9 @@ could be wrapped, but they had to be renamed. For example:
     class Foo {
     public:
    -    Foo();
    +  Foo();
       %name(CopyFoo) Foo(const Foo &);
    -    ...
    +  ...
     };
     
    @@ -948,9 +969,9 @@ Alternatively, you can specify an immutable member in advance like this: %immutable List::length; ... class List { - ... - int length; // Immutable by above directive - ... + ... + int length; // Immutable by above directive + ... }; @@ -969,8 +990,8 @@ not primitive types, such as classes. For instance, if you had another class lik
     class Foo {
     public:
    -    List items;
    -    ...
    +  List items;
    +  ...
     
    @@ -982,10 +1003,10 @@ For example:
     List *Foo_items_get(Foo *self) {
    -    return &self->items;
    +  return &self->items;
     }
     void Foo_items_set(Foo *self, List *value) {
    -    self->items = *value;
    +  self->items = *value;
     }
     
    @@ -1007,10 +1028,10 @@ It is the naturalvar feature and can be used to effectively change the way acces
     const List &Foo_items_get(Foo *self) {
    -    return self->items;
    +  return self->items;
     }
     void Foo_items_set(Foo *self, const List &value) {
    -    self->items = value;
    +  self->items = value;
     }
     
    @@ -1078,7 +1099,7 @@ like this
     struct Foo {
    -   size_t  len;
    +  size_t  len;
     };
     
    @@ -1094,113 +1115,7 @@ a few problems related to structure wrapping and some of SWIG's customization features.

    -

    6.7 Default arguments

    - - -

    -SWIG will wrap all types of functions that have default arguments. For example member functions: -

    - -
    -
    -class Foo {
    -public:
    -    void bar(int x, int y = 3, int z = 4);
    -};
    -
    -
    - -

    -SWIG handles default arguments by generating an extra overloaded method for each defaulted argument. -SWIG is effectively handling methods with default arguments as if it was wrapping the equivalent overloaded methods. -Thus for the example above, it is as if we had instead given the following to SWIG: -

    - -
    -
    -class Foo {
    -public:
    -    void bar(int x, int y, int z);
    -    void bar(int x, int y);
    -    void bar(int x);
    -};
    -
    -
    - -

    -The wrappers produced are exactly the same as if the above code was instead fed into SWIG. -Details of this are covered later in the Wrapping Overloaded Functions and Methods section. -This approach allows SWIG to wrap all possible default arguments, but can be verbose. -For example if a method has ten default arguments, then eleven wrapper methods are generated. -

    - -

    -Please see the Features and default arguments -section for more information on using %feature with functions with default arguments. -The Ambiguity resolution and renaming section -also deals with using %rename and %ignore on methods with default arguments. -If you are writing your own typemaps for types used in methods with default arguments, you may also need to write a typecheck typemap. -See the Typemaps and overloading section for details or otherwise -use the compactdefaultargs feature flag as mentioned below. -

    - -

    -Compatibility note: Versions of SWIG prior to SWIG-1.3.23 wrapped default arguments slightly differently. -Instead a single wrapper method was generated and the default values were copied into the C++ wrappers -so that the method being wrapped was then called with all the arguments specified. -If the size of the wrappers are a concern then this approach to wrapping methods with default arguments -can be re-activated by using the compactdefaultargs -feature flag. -

    - -
    -
    -%feature("compactdefaultargs") Foo::bar;
    -class Foo {
    -public:
    -    void bar(int x, int y = 3, int z = 4);
    -};
    -
    -
    - - -

    -This is great for reducing the size of the wrappers, but the caveat is it does not work for the statically typed languages, -such as C# and Java, -which don't have optional arguments in the language, -Another restriction of this feature is that it cannot handle default arguments that are not public. -The following example illustrates this: -

    - -
    -
    -class Foo {
    -private:
    -   static const int spam;
    -public:
    -   void bar(int x, int y = spam);   // Won't work with %feature("compactdefaultargs") -
    -                                    // private default value
    -};
    -
    -
    - -

    -This produces uncompilable wrapper code because default values in C++ are -evaluated in the same scope as the member function whereas SWIG -evaluates them in the scope of a wrapper function (meaning that the -values have to be public). -

    - -

    -The compactdefaultargs feature is automatically turned on when wrapping C code with default arguments. -Some target languages will also automatically turn on this feature -if the keyword arguments feature (kwargs) is specified for either C or C++ functions, and the target language supports kwargs, -the compactdefaultargs feature is also automatically turned on. -Keyword arguments are a language feature of some scripting languages, for example Ruby and Python. -SWIG is unable to support kwargs when wrapping overloaded methods, so the default approach cannot be used. -

    - -

    6.8 Protection

    +

    6.7 Protection

    @@ -1220,7 +1135,7 @@ until you explicitly give a `public:' declaration (This is the same convention used by C++).

    -

    6.9 Enums and constants

    +

    6.8 Enums and constants

    @@ -1250,7 +1165,7 @@ Swig_STOUT = Swig::STOUT Members declared as const are wrapped as read-only members and do not create constants.

    -

    6.10 Friends

    +

    6.9 Friends

    @@ -1262,9 +1177,9 @@ you have this code:

     class Foo {
     public:
    -     ...
    -     friend void blah(Foo *f);
    -     ...
    +  ...
    +  friend void blah(Foo *f);
    +  ...
     };
     
    @@ -1278,7 +1193,7 @@ equivalent to one generated for the following declaration
     class Foo {
     public:
    -    ...
    +  ...
     };
     
     void blah(Foo *f);    
    @@ -1299,9 +1214,9 @@ namespace bar {
     
       class Foo {
       public:
    -     ...
    -     friend void blah(Foo *f);
    -     ...
    +    ...
    +    friend void blah(Foo *f);
    +    ...
       };
     }
     
    @@ -1311,7 +1226,7 @@ namespace bar { and a wrapper for the method 'blah' will not be generated.

    -

    6.11 References and pointers

    +

    6.10 References and pointers

    @@ -1364,7 +1279,7 @@ For example:

     class Bar {
     public:
    -     Foo &spam();
    +  Foo &spam();
     };
     
    @@ -1376,8 +1291,8 @@ Generates an accessor like this:
     Foo *Bar_spam(Bar *obj) {
    -   Foo &result = obj->spam();
    -   return &result;
    +  Foo &result = obj->spam();
    +  return &result;
     }
     
    @@ -1411,7 +1326,7 @@ templates and the STL. This was first added in SWIG-1.3.12.

    -

    6.12 Pass and return by value

    +

    6.11 Pass and return by value

    @@ -1433,10 +1348,10 @@ following:

     Vector *wrap_cross_product(Vector *a, Vector *b) {
    -   Vector x = *a;
    -   Vector y = *b;
    -   Vector r = cross_product(x,y);
    -   return new Vector(r);
    +  Vector x = *a;
    +  Vector y = *b;
    +  Vector r = cross_product(x, y);
    +  return new Vector(r);
     }
    @@ -1455,10 +1370,10 @@ called the "Fulton Transform". This produces a wrapper that looks like this:
     Vector cross_product(Vector *a, Vector *b) {
    -   SwigValueWrapper<Vector> x = *a;
    -   SwigValueWrapper<Vector> y = *b;
    -   SwigValueWrapper<Vector> r = cross_product(x,y);
    -   return new Vector(r);
    +  SwigValueWrapper<Vector> x = *a;
    +  SwigValueWrapper<Vector> y = *b;
    +  SwigValueWrapper<Vector> r = cross_product(x, y);
    +  return new Vector(r);
     }
     
    @@ -1485,8 +1400,8 @@ class A; %feature("valuewrapper") B; struct B { - B(); - // .... + B(); + // .... }; @@ -1515,7 +1430,7 @@ classes that don't define a default constructor. It is not used for C++ pointers or references.

    -

    6.13 Inheritance

    +

    6.12 Inheritance

    @@ -1550,7 +1465,7 @@ the full C++ code has been omitted.

    class Shape { public: - double x,y; + double x, y; virtual double area() = 0; virtual double perimeter() = 0; void set_location(double x, double y); @@ -1586,7 +1501,7 @@ $ python 153.93804004599999757 >>> print shapes.Shape_area(square) 100.00000000000000000 ->>> shapes.Shape_set_location(square,2,-3) +>>> shapes.Shape_set_location(square, 2, -3) >>> print shapes.Shape_perimeter(square) 40.00000000000000000 >>> @@ -1672,7 +1587,7 @@ Similarly, typedef allows unnamed structures to be used as base classes
     typedef struct {
    -   ...
    +  ...
     } Foo;
     
     class Bar : public Foo {    // Ok. 
    @@ -1701,7 +1616,7 @@ functions for virtual members that are already defined in a base
     class.
     

    -

    6.14 A brief discussion of multiple inheritance, pointers, and type checking

    +

    6.13 A brief discussion of multiple inheritance, pointers, and type checking

    @@ -1741,23 +1656,23 @@ inheritance. For example, suppose you had code like this:

     class A {
     public:
    -   int x;
    +  int x;
     };
     
     class B {
     public:
    -   int y;
    +  int y;
     };
     
     class C : public A, public B {
     };
     
     int A_function(A *a) {
    -   return a->x;
    +  return a->x;
     }
     
     int B_function(B *b) {
    -   return b->y;
    +  return b->y;
     }
     
    @@ -1833,7 +1748,113 @@ int y = B_function((B *) pB); In practice, the pointer is held as an integral number in the target language proxy class.

    -

    6.15 Wrapping Overloaded Functions and Methods

    +

    6.14 Default arguments

    + + +

    +SWIG will wrap all types of functions that have default arguments. For example member functions: +

    + +
    +
    +class Foo {
    +public:
    +  void bar(int x, int y = 3, int z = 4);
    +};
    +
    +
    + +

    +SWIG handles default arguments by generating an extra overloaded method for each defaulted argument. +SWIG is effectively handling methods with default arguments as if it was wrapping the equivalent overloaded methods. +Thus for the example above, it is as if we had instead given the following to SWIG: +

    + +
    +
    +class Foo {
    +public:
    +  void bar(int x, int y, int z);
    +  void bar(int x, int y);
    +  void bar(int x);
    +};
    +
    +
    + +

    +The wrappers produced are exactly the same as if the above code was instead fed into SWIG. +Details of this are covered in the next section Overloaded functions and methods. +This approach allows SWIG to wrap all possible default arguments, but can be verbose. +For example if a method has ten default arguments, then eleven wrapper methods are generated. +

    + +

    +Please see the Features and default arguments +section for more information on using %feature with functions with default arguments. +The Renaming and ambiguity resolution section +also deals with using %rename and %ignore on methods with default arguments. +If you are writing your own typemaps for types used in methods with default arguments, you may also need to write a typecheck typemap. +See the Typemaps and overloading section for details or otherwise +use the compactdefaultargs feature flag as mentioned below. +

    + +

    +Compatibility note: Versions of SWIG prior to SWIG-1.3.23 wrapped default arguments slightly differently. +Instead a single wrapper method was generated and the default values were copied into the C++ wrappers +so that the method being wrapped was then called with all the arguments specified. +If the size of the wrappers are a concern then this approach to wrapping methods with default arguments +can be re-activated by using the compactdefaultargs +feature flag. +

    + +
    +
    +%feature("compactdefaultargs") Foo::bar;
    +class Foo {
    +public:
    +  void bar(int x, int y = 3, int z = 4);
    +};
    +
    +
    + + +

    +This is great for reducing the size of the wrappers, but the caveat is it does not work for the statically typed languages, +such as C# and Java, +which don't have optional arguments in the language, +Another restriction of this feature is that it cannot handle default arguments that are not public. +The following example illustrates this: +

    + +
    +
    +class Foo {
    +private:
    +  static const int spam;
    +public:
    +  void bar(int x, int y = spam);   // Won't work with %feature("compactdefaultargs") -
    +                                   // private default value
    +};
    +
    +
    + +

    +This produces uncompilable wrapper code because default values in C++ are +evaluated in the same scope as the member function whereas SWIG +evaluates them in the scope of a wrapper function (meaning that the +values have to be public). +

    + +

    +The compactdefaultargs feature is automatically turned on when wrapping C code with default arguments. +Some target languages will also automatically turn on this feature +if the keyword arguments feature (kwargs) is specified for either C or C++ functions, and the target language supports kwargs, +the compactdefaultargs feature is also automatically turned on. +Keyword arguments are a language feature of some scripting languages, for example Ruby and Python. +SWIG is unable to support kwargs when wrapping overloaded methods, so the default approach cannot be used. +

    + +

    6.15 Overloaded functions and methods

    @@ -1844,10 +1865,10 @@ constructors. For example, if you supply SWIG with overloaded functions like th

     void foo(int x) {
    -   printf("x is %d\n", x);
    +  printf("x is %d\n", x);
     }
     void foo(char *x) {
    -   printf("x is '%s'\n", x);
    +  printf("x is '%s'\n", x);
     }
     
    @@ -1875,10 +1896,10 @@ this code,
     class Foo {
     public:
    -     Foo();
    -     Foo(const Foo &);   // Copy constructor
    -     void bar(int x);
    -     void bar(char *s, int y);
    +  Foo();
    +  Foo(const Foo &);   // Copy constructor
    +  void bar(int x);
    +  void bar(char *s, int y);
     };
     
    @@ -1892,7 +1913,7 @@ it might be used like this >>> f = Foo() # Create a Foo >>> f.bar(3) >>> g = Foo(f) # Copy Foo ->>> f.bar("hello",2) +>>> f.bar("hello", 2) @@ -2021,7 +2042,7 @@ checked in the same order as they appear in this ranking. If you're still confused, don't worry about it---SWIG is probably doing the right thing.

    -

    6.15.2 Ambiguity in Overloading

    +

    6.15.2 Ambiguity in overloading

    @@ -2129,7 +2150,7 @@ If you get an error message such as the following,

     foo.i:6. Overloaded declaration ignored.  Spam::foo(double )
     foo.i:5. Previous declaration is Spam::foo(int )
    -foo.i:7. Overloaded declaration ignored.  Spam::foo(Bar *,Spam *,int )
    +foo.i:7. Overloaded declaration ignored.  Spam::foo(Bar *, Spam *, int )
     foo.i:5. Previous declaration is Spam::foo(int )
     
    @@ -2139,7 +2160,7 @@ it means that the target language module has not yet implemented support for ove functions and methods. The only way to fix the problem is to read the next section.

    -

    6.15.3 Ambiguity resolution and renaming

    +

    6.15.3 Renaming and ambiguity resolution

    @@ -2193,9 +2214,9 @@ void foo(char *c); // Stays 'foo' (not renamed) class Spam { public: - void foo(int); // Becomes 'foo_i' - void foo(double); // Becomes 'foo_d' - ... + void foo(int); // Becomes 'foo_i' + void foo(double); // Becomes 'foo_d' + ... }; @@ -2227,23 +2248,23 @@ an entire class hierarchy with only a few declarations. For example: class Spam { public: - virtual void foo(int); // Renamed to foo_i - virtual void foo(double); // Renamed to foo_d - ... + virtual void foo(int); // Renamed to foo_i + virtual void foo(double); // Renamed to foo_d + ... }; class Bar : public Spam { public: - virtual void foo(int); // Renamed to foo_i - virtual void foo(double); // Renamed to foo_d -... + virtual void foo(int); // Renamed to foo_i + virtual void foo(double); // Renamed to foo_d + ... }; class Grok : public Bar { public: - virtual void foo(int); // Renamed to foo_i - virtual void foo(double); // Renamed to foo_d -... + virtual void foo(int); // Renamed to foo_i + virtual void foo(double); // Renamed to foo_d + ... }; @@ -2256,18 +2277,18 @@ class definition itself. For example:

     class Spam {
    -   %rename(foo_i) foo(int);
    -   %rename(foo_d) foo(double);
    +  %rename(foo_i) foo(int);
    +  %rename(foo_d) foo(double);
     public:
    -   virtual void foo(int);      // Renamed to foo_i
    -   virtual void foo(double);   // Renamed to foo_d
    -   ...
    +  virtual void foo(int);      // Renamed to foo_i
    +  virtual void foo(double);   // Renamed to foo_d
    +  ...
     };
     
     class Bar : public Spam {
     public:
    -   virtual void foo(int);      // Renamed to foo_i
    -   virtual void foo(double);   // Renamed to foo_d
    +  virtual void foo(int);      // Renamed to foo_i
    +  virtual void foo(double);   // Renamed to foo_d
     ...
     };
     
    @@ -2399,16 +2420,16 @@ the first renaming rule found on a depth-first traversal of the class hierarchy is used.
  • -
  • The name matching rules strictly follow member qualification rules. -For example, if you have a class like this:

    +
  • The name matching rules strictly follow member qualifier rules. +For example, if you have a class and member with a member that is const qualified like this:

     class Spam {
     public:
    -   ...
    -   void bar() const;
    -   ...
    +  ...
    +  void bar() const;
    +  ...
     };
     
    @@ -2424,7 +2445,7 @@ the declaration

    -will not apply as there is no unqualified member bar(). The following will apply as +will not apply as there is no unqualified member bar(). The following will apply the rename as the qualifier matches correctly:

    @@ -2434,6 +2455,26 @@ the qualifier matches correctly: +

    +Similarly for combinations of cv-qualifiers and ref-qualifiers, all the qualifiers must be specified to match correctly: +

    + +
    +
    +%rename(name) Jam::bar();          // will not match
    +%rename(name) Jam::bar() &;        // will not match
    +%rename(name) Jam::bar() const;    // will not match
    +%rename(name) Jam::bar() const &;  // ok, will match
    +
    +class Jam {
    +public:
    +  ...
    +  void bar() const &;
    +  ...
    +};
    +
    +
    +

    An often overlooked C++ feature is that classes can define two different overloaded members that differ only in their qualifiers, like this: @@ -2443,10 +2484,10 @@ that differ only in their qualifiers, like this:

     class Spam {
     public:
    -   ...
    -   void bar();         // Unqualified member
    -   void bar() const;   // Qualified member
    -   ...
    +  ...
    +  void bar();         // Unqualified member
    +  void bar() const;   // Qualified member
    +  ...
     };
     
    @@ -2466,7 +2507,7 @@ For example we can give them separate names in the target language:

    Similarly, if you merely wanted to ignore one of the declarations, use %ignore -with the full qualification. For example, the following directive +with the full qualifier. For example, the following directive would tell SWIG to ignore the const version of bar() above:

    @@ -2492,11 +2533,11 @@ typedef int Integer; class Spam { public: - void foo(Integer); // Stays 'foo' (not renamed) + void foo(Integer); // Stays 'foo' (not renamed) }; class Ham { public: - void foo(int); // Renamed to foo_i + void foo(int); // Renamed to foo_i }; @@ -2511,9 +2552,9 @@ Let's consider the following example class:

     class Spam {
     public:
    -   ...
    -   void bar(int i=-1, double d=0.0);
    -   ...
    +  ...
    +  void bar(int i=-1, double d=0.0);
    +  ...
     };
     
    @@ -2532,8 +2573,7 @@ exactly matches the wrapped method:

    The C++ method can then be called from the target language with the new name no matter how many arguments are specified, for example: newbar(2, 2.0), newbar(2) or newbar(). -However, if the %rename does not contain the default arguments, it will only apply to the single equivalent target language overloaded method. -So if instead we have: +However, if the %rename does not contain the default arguments:

    @@ -2542,9 +2582,24 @@ So if instead we have:
    +

    +then only one of the three equivalent overloaded methods will be renamed and wrapped as if SWIG parsed: +

    + +
    +
    +void Spam::newbar(int i, double d);
    +void Spam::bar(int i);
    +void Spam::bar();
    +
    +
    +

    The C++ method must then be called from the target language with the new name newbar(2, 2.0) when both arguments are supplied or with the original name as bar(2) (one argument) or bar() (no arguments). +

    + +

    In fact it is possible to use %rename on the equivalent overloaded methods, to rename all the equivalent overloaded methods:

    @@ -2586,7 +2641,7 @@ As a general rule, statically typed languages like Java are able to provide more than dynamically typed languages like Perl, Python, Ruby, and Tcl.

    -

    6.16 Wrapping overloaded operators

    +

    6.16 Overloaded operators

    @@ -2660,9 +2715,9 @@ something like this pseudocode:

     _wrap_Complex___add__(args) {
    -   ... get args ...
    -   obj->operator+(args);
    -   ...
    +  ... get args ...
    +  obj->operator+(args);
    +  ...
     }
     
    @@ -2674,8 +2729,8 @@ operator normally. For example:
    ->>> a = Complex(3,4)
    ->>> b = Complex(5,2)
    +>>> a = Complex(3, 4)
    +>>> b = Complex(5, 2)
     >>> c = a + b           # Invokes __add__ method
     
    @@ -2698,8 +2753,8 @@ The resulting scripting interface might work like this:
    -a = Complex(3,4)
    -b = Complex(5,2)
    +a = Complex(3, 4)
    +b = Complex(5, 2)
     c = a.add(b)      # Call a.operator+(b)
     
    @@ -2763,8 +2818,27 @@ have to handle it like a normal function. For example:
  • Certain operators are ignored by default. For instance, new and delete operators -are ignored as well as conversion operators. -

  • +are ignored as well as conversion and index operators. A warning such as the one below is shown: +

    + +
    +
    +example.i:12: Warning 503: Can't wrap 'operator []' unless renamed to a valid identifier.
    +
    +
    + + +
  • The index operator, operator[], is particularly difficult to overload due to differences in C++ +implementations. Specifically, the get and set operators in other languages typically are separated +into two methods such that additional logic can be packed into the operations; C# uses +this[type key] { get { ... } set { ... }}, Python uses +__getitem__ and __setitem__, etc. In C++ if the return +type of operator[] is a reference and the method is const, it is often indicative of the setter, +and the getter is usually a const function return an object by value. +In the absence of any hard and fast rules and the fact that there may be multiple index operators, +it is up to the user to choose the getter and setter to use by using %rename as shown earlier. +

    +
  • The semantics of certain C++ operators may not match those in the target language.
  • @@ -2788,14 +2862,14 @@ example : class Vector { public: - double x,y,z; + double x, y, z; Vector(); ~Vector(); ... bunch of C++ methods ... %extend { char *__str__() { static char temp[256]; - sprintf(temp,"[ %g, %g, %g ]", $self->x,$self->y,$self->z); + sprintf(temp, "[ %g, %g, %g ]", $self->x, $self->y, $self->z); return &temp[0]; } } @@ -2880,7 +2954,7 @@ is expected in an interface file. For example:
     void foo(vector<int> *a, int n);
    -void bar(list<int,100> *x);
    +void bar(list<int, 100> *x);
     
    @@ -2893,9 +2967,9 @@ and '>' within a constant expressions currently is not supported by SWIG
    -void bar(list<int,100> *x);                // OK
    -void bar(list<int,2*50> *x);               // OK
    -void bar(list<int,(2>1 ? 100 : 50)> *x)    // Not supported
    +void bar(list<int, 100> *x);                // OK
    +void bar(list<int, 2*50> *x);               // OK
    +void bar(list<int, (2>1 ? 100 : 50)> *x)    // Not supported
     
    @@ -2917,63 +2991,76 @@ as vector<int>. The wrapper for foo() will accept either variant.

    +

    6.18.1 The %template directive

    + +

    -Starting with SWIG-1.3.7, simple C++ template declarations can also be -wrapped. SWIG-1.3.12 greatly expands upon the earlier implementation. Before discussing this any further, there are a few things -you need to know about template wrapping. First, a bare C++ template +There are a couple of important points about template wrapping. +First, a bare C++ template does not define any sort of runnable object-code for which SWIG can normally create a wrapper. Therefore, in order to wrap a template, you need to give SWIG information about a particular template -instantiation (e.g., vector<int>, +instantiation (e.g., vector<int>, array<double>, etc.). Second, an instantiation name such as vector<int> is generally not a valid identifier name in most target languages. Thus, you will need to give the -template instantiation a more suitable name such as intvector -when creating a wrapper. +template instantiation a more suitable name such as intvector.

    -To illustrate, consider the following template definition: +To illustrate, consider the following class template definition:

     template<class T> class List {
     private:
    -    T *data;
    -    int nitems;
    -    int maxitems;
    +  T *data;
    +  int nitems;
    +  int maxitems;
     public:
    -    List(int max) {
    -      data = new T [max];
    -      nitems = 0;
    -      maxitems = max;
    -    }
    -    ~List() {
    -      delete [] data;
    -    };
    -    void append(T obj) {
    -      if (nitems < maxitems) {
    -        data[nitems++] = obj;
    -      }
    -    }
    -    int length() {
    -      return nitems;
    -    }
    -    T get(int n) {
    -      return data[n];
    +  List(int max) {
    +    data = new T [max];
    +    nitems = 0;
    +    maxitems = max;
    +  }
    +  ~List() {
    +    delete [] data;
    +  };
    +  void append(T obj) {
    +    if (nitems < maxitems) {
    +      data[nitems++] = obj;
         }
    +  }
    +  int length() {
    +    return nitems;
    +  }
    +  T get(int n) {
    +    return data[n];
    +  }
     };
     

    -By itself, this template declaration is useless--SWIG simply ignores it -because it doesn't know how to generate any code until unless a definition of +By itself, this class template is useless--SWIG simply ignores it +because it doesn't know how to generate any code unless a definition of T is provided. +The %template directive is required to instantiate the template for use in a target language. +The directive requires an identifier name for use in the target language plus the template for instantiation. +The example below instantiates List<int> for use as a class named intList:

    +
    +
    +%template(intList) List<int>;
    +
    +
    +

    -One way to create wrappers for a specific template instantiation is to simply -provide an expanded version of the class directly like this: +The instantiation expands the template code as a C++ compiler would do and then makes it available +under the given identifier name. +Essentially it is the same as wrapping the following concept code where +the class template definition has T expanded to int +(note that this is not entirely valid syntax):

    @@ -2981,42 +3068,20 @@ provide an expanded version of the class directly like this: %rename(intList) List<int>; // Rename to a suitable identifier class List<int> { private: - int *data; - int nitems; - int maxitems; + int *data; + int nitems; + int maxitems; public: - List(int max); - ~List(); - void append(int obj); - int length(); - int get(int n); + List(int max); + ~List(); + void append(int obj); + int length(); + int get(int n); };
    -

    -The %rename directive is needed to give the template class an appropriate identifier -name in the target language (most languages would not recognize C++ template syntax as a valid -class name). The rest of the code is the same as what would appear in a normal -class definition. -

    - -

    -Since manual expansion of templates gets old in a hurry, the %template directive can -be used to create instantiations of a template class. Semantically, %template is -simply a shortcut---it expands template code in exactly the same way as shown above. Here -are some examples: -

    - -
    -
    -/* Instantiate a few different versions of the template */
    -%template(intList) List<int>;
    -%template(doubleList) List<double>;
    -
    -
    -

    The argument to %template() is the name of the instantiation in the target language. The name you choose should not conflict with @@ -3034,7 +3099,81 @@ typedef List<int> intList; // OK

    -SWIG can also generate wrappers for function templates using a similar technique. +The %template directive +must always appear after the definition of the template to be expanded, so the following will work: +

    + +
    +
    +template<class T> class List { ... };
    +%template(intList) List<int>;
    +
    +
    + +

    +but if %template is used before the template definition, such as: +

    + +
    +
    +%template(intList) List<int>;
    +template<class T> class List { ... };
    +
    +
    + +

    +SWIG will generate an error: +

    + +
    +
    +example.i:3: Error: Template 'List' undefined.
    +
    +
    + +

    +Since the type system knows how to handle typedef, it is +generally not necessary to instantiate different versions of a template +for typenames that are equivalent. For instance, consider this code: +

    + +
    +
    +%template(intList) List<int>;
    +typedef int Integer;
    +...
    +void foo(List<Integer> *x);
    +
    +
    + +

    +In this case, List<Integer> is exactly the same type as +List<int>. Any use of List<Integer> is mapped back to the +instantiation of List<int> created earlier. Therefore, it is +not necessary to instantiate a new class for the type Integer (doing so is +redundant and will simply result in code bloat). +

    + +

    +The template provided to %template for instantiation must be the actual template and not a typedef to a template. +

    + +
    +
    +typedef List<int> ListOfInt;
    +
    +%template(intList) List<int>; // ok
    +%template(intList) ListOfInt; // illegal - Syntax error
    +
    +
    + + +

    6.18.2 Function templates

    + + +

    +SWIG can also generate wrappers for function templates using a similar technique +to that shown above for class templates. For example:

    @@ -3054,6 +3193,28 @@ In this case, maxint and maxdouble become unique names for spe instantiations of the function.

    +

    +SWIG even supports overloaded templated functions. As usual the %template directive +is used to wrap templated functions. For example: +

    + +
    +
    +template<class T> void foo(T x) { };
    +template<class T> void foo(T x, T y) { };
    +
    +%template(foo) foo<int>;
    +
    +
    + +

    +This will generate two overloaded wrapper methods, the first will take a single integer as an argument +and the second will take two integer arguments. +

    + +

    6.18.3 Default template arguments

    + +

    The number of arguments supplied to %template should match that in the original template definition. Template default arguments are supported. For example: @@ -3066,7 +3227,7 @@ template vector<typename T, int max=100> class vector { }; %template(intvec) vector<int>; // OK -%template(vec1000) vector<int,1000>; // OK +%template(vec1000) vector<int, 1000>; // OK @@ -3091,28 +3252,8 @@ instantiation only once in order to reduce the potential for code bloat.

    -

    -Since the type system knows how to handle typedef, it is -generally not necessary to instantiate different versions of a template -for typenames that are equivalent. For instance, consider this code: -

    +

    6.18.4 Template base classes

    -
    -
    -%template(intList) vector<int>;
    -typedef int Integer;
    -...
    -void foo(vector<Integer> *x);
    -
    -
    - -

    -In this case, vector<Integer> is exactly the same type as -vector<int>. Any use of Vector<Integer> is mapped back to the -instantiation of vector<int> created earlier. Therefore, it is -not necessary to instantiate a new class for the type Integer (doing so is -redundant and will simply result in code bloat). -

    When a template is instantiated using %template, information @@ -3126,7 +3267,7 @@ For example, if you wrote code like this, %template(intList) List<int>; ... class UltraList : public List<int> { - ... + ... }; @@ -3139,13 +3280,13 @@ nothing is known about List<int>, you will get a warning message

    -example.h:42: Warning 401. Nothing known about class 'List<int >'. Ignored. 
    -example.h:42: Warning 401. Maybe you forgot to instantiate 'List<int >' using %template. 
    +example.h:42: Warning 401. Nothing known about class 'List< int >'. Ignored. 
    +example.h:42: Warning 401. Maybe you forgot to instantiate 'List< int >' using %template. 
     

    -If a template class inherits from another template class, you need to +If a class template inherits from another class template, you need to make sure that base classes are instantiated before derived classes. For example:

    @@ -3186,8 +3327,8 @@ use the empty template instantiation, that is, %template with no name.
    -// Instantiate traits<double,double>, but don't wrap it.
    -%template() traits<double,double>;
    +// Instantiate traits<double, double>, but don't wrap it.
    +%template() traits<double, double>;
     
    @@ -3216,6 +3357,9 @@ TEMPLATE_WRAP(PairStringInt, std::pair<string, int>) Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in the last example would not be possible.

    +

    6.18.5 Template specialization

    + +

    The SWIG template mechanism does support specialization. For instance, if you define a class like this, @@ -3225,15 +3369,15 @@ a class like this,

     template<> class List<int> {
     private:
    -    int *data;
    -    int nitems;
    -    int maxitems;
    +  int *data;
    +  int nitems;
    +  int maxitems;
     public:
    -    List(int max);
    -    ~List();
    -    void append(int obj);
    -    int length();
    -    int get(int n);
    +  List(int max);
    +  ~List();
    +  void append(int obj);
    +  int length();
    +  int get(int n);
     };
     
    @@ -3256,15 +3400,15 @@ code defines a template that is applied when the template argument is a pointer.
     template<class T> class List<T*> {
     private:
    -    T *data;
    -    int nitems;
    -    int maxitems;
    +  T *data;
    +  int nitems;
    +  int maxitems;
     public:
    -    List(int max);
    -    ~List();
    -    void append(int obj);
    -    int length();
    -    T get(int n);
    +  List(int max);
    +  ~List();
    +  void append(T obj);
    +  int length();
    +  T get(int n);
     };
     
    @@ -3303,10 +3447,13 @@ SWIG implements template argument deduction so that the following partial specia +

    6.18.6 Member templates

    + +

    -Member function templates are supported. The underlying principle is the same +Member templates are supported. The underlying principle is the same as for normal templates--SWIG can't create a wrapper unless you provide -more information about types. For example, a class with a member template might +more information about types. For example, a class with a member function template might look like this:

    @@ -3314,8 +3461,8 @@ look like this:
     class Foo {
     public:
    -     template<class T> void bar(T x, T y) { ... };
    -     ...
    +  template<class T> void bar(T x, T y) { ... };
    +  ...
     };
     
    @@ -3328,10 +3475,10 @@ To expand the template, simply use %template inside the class.
     class Foo {
     public:
    -     template<class T> void bar(T x, T y) { ... };
    -     ...
    -     %template(barint)    bar<int>;
    -     %template(bardouble) bar<double>;
    +  template<class T> void bar(T x, T y) { ... };
    +  ...
    +  %template(barint)    bar<int>;
    +  %template(bardouble) bar<double>;
     };
     
    @@ -3344,13 +3491,13 @@ Or, if you want to leave the original class definition alone, just do this:
     class Foo {
     public:
    -     template<class T> void bar(T x, T y) { ... };
    -     ...
    +  template<class T> void bar(T x, T y) { ... };
    +  ...
     };
     ...
     %extend Foo {
    -     %template(barint)    bar<int>;
    -     %template(bardouble) bar<double>;
    +  %template(barint)    bar<int>;
    +  %template(bardouble) bar<double>;
     };
     
    @@ -3363,8 +3510,8 @@ or simply
     class Foo {
     public:
    -     template<class T> void bar(T x, T y) { ... };
    -     ...
    +  template<class T> void bar(T x, T y) { ... };
    +  ...
     };
     ...
     
    @@ -3380,11 +3527,6 @@ methods to the Foo class.
     

    -

    -Note: because of the way that templates are handled, the %template directive -must always appear after the definition of the template to be expanded. -

    -

    Now, if your target language supports overloading, you can even try

    @@ -3405,7 +3547,7 @@ depending on the argument type.

    When used with members, the %template directive may be placed in another -template class. Here is a slightly perverse example: +class template. Here is a slightly perverse example:

    @@ -3413,9 +3555,9 @@ template class. Here is a slightly perverse example: // A template template<class T> class Foo { public: - // A member template - template<class S> T bar(S x, S y) { ... }; - ... + // A member template + template<class S> T bar(S x, S y) { ... }; + ... }; // Expand a few member templates @@ -3443,12 +3585,12 @@ and conversions. For example:
     template<class T1, class T2> struct pair {
    -   T1 first;
    -   T2 second;
    -   pair() : first(T1()), second(T2()) { }
    -   pair(const T1 &x, const T2 &y) : first(x), second(y) { }
    -   template<class U1, class U2> pair(const pair<U1,U2> &x) 
    -                                        : first(x.first),second(x.second) { }
    +  T1 first;
    +  T2 second;
    +  pair() : first(T1()), second(T2()) { }
    +  pair(const T1 &x, const T2 &y) : first(x), second(y) { }
    +  template<class U1, class U2> pair(const pair<U1, U2> &x)
    +                                       : first(x.first), second(x.second) { }
     };
     
    @@ -3456,13 +3598,13 @@ template<class T1, class T2> struct pair {

    This declaration is perfectly acceptable to SWIG, but the constructor template will be ignored unless you explicitly expand it. To do that, you could expand a few versions of the constructor -in the template class itself. For example: +in the class template itself. For example:

     %extend pair {
    -   %template(pair) pair<T1,T2>;        // Generate default copy constructor
    +  %template(pair) pair<T1, T2>;        // Generate default copy constructor
     };
     
    @@ -3479,18 +3621,18 @@ Alternatively, you could expand the constructor template in selected instantiati
     // Instantiate a few versions
    -%template(pairii) pair<int,int>;
    -%template(pairdd) pair<double,double>;
    +%template(pairii) pair<int, int>;
    +%template(pairdd) pair<double, double>;
     
     // Create a default constructor only 
    -%extend pair<int,int> {
    -   %template(paird) pair<int,int>;         // Default constructor
    +%extend pair<int, int> {
    +  %template(paird) pair<int, int>;         // Default constructor
     };
     
     // Create default and conversion constructors 
    -%extend pair<double,double> {
    -   %template(paird) pair<double,dobule>;   // Default constructor
    -   %template(pairc) pair<int,int>;         // Conversion constructor
    +%extend pair<double, double> {
    +  %template(paird) pair<double, dobule>;   // Default constructor
    +  %template(pairc) pair<int, int>;         // Conversion constructor
     };
     
    @@ -3503,9 +3645,9 @@ instead:
     // Create default and conversion constructors 
    -%extend pair<double,double> {
    -   %template(pair) pair<double,dobule>;   // Default constructor
    -   %template(pair) pair<int,int>;         // Conversion constructor
    +%extend pair<double, double> {
    +  %template(pair) pair<double, dobule>;   // Default constructor
    +  %template(pair) pair<int, int>;         // Conversion constructor
     };
     
    @@ -3517,6 +3659,110 @@ constructor, that will dispatch the proper call depending on the argument type.

    +

    6.18.7 Scoping and templates

    + + +

    +The %template directive for a class template is the equivalent to an explicit instantiation +of a C++ class template. The scope for a valid %template instantiation is the same +as the scope required for a valid explicit instantiation of a C++ template. +A definition of the template for the explicit instantiation must be in scope +where the instantiation is declared and must not be enclosed within a different namespace. +

    + +

    +For example, a few %template instantiations and C++ explicit instantiations are shown below: +

    + +
    +
    +namespace N {
    +  template<typename T> class C {};
    +}
    +
    +// valid
    +%template(cin) N::C<int>;
    +template class N::C<int>;
    +
    +// valid
    +namespace N {
    +  %template(cin) C<int>;
    +  template class C<int>;
    +}
    +
    +// valid
    +using namespace N;
    +%template(cin) C<int>;
    +template class C<int>;
    +
    +// valid
    +using N::C;
    +%template(cin) C<int>;
    +template class C<int>;
    +
    +// ill-formed
    +namespace unrelated {
    +  using N::C;
    +  %template(cin) C<int>;
    +  template class C<int>;
    +}
    +
    +// ill-formed
    +namespace unrelated {
    +  using namespace N;
    +  %template(cin) C<int>;
    +  template class C<int>;
    +}
    +
    +// ill-formed
    +namespace unrelated {
    +  namespace N {
    +    %template(cin) C<int>;
    +    template class C<int>;
    +  }
    +}
    +
    +// ill-formed
    +namespace unrelated {
    +  %template(cin) N::C<int>;
    +  template class N::C<int>;
    +}
    +
    +
    + +

    +When the scope is incorrect, such as for the ill-formed examples above, an error occurs: +

    + +
    +
    +cpp_template_scope.i:34: Error: 'C' resolves to 'N::C' and was incorrectly instantiated
    +in scope 'unrelated' instead of within scope 'N'.
    +
    +
    + +

    +A note for the C++ standard geeks out there; a valid instantiation is one which conforms to +the C++03 standard as C++11 made a change to disallow using declarations and using directives to find a template. +

    + +
    +
    +// valid C++03, ill-formed C++11
    +using N::C;
    +template class C<int>;
    +
    +
    + +

    +Compatibility Note: Versions prior to SWIG-4.0.0 did not error out with incorrectly scoped +%template declarations, but this led to numerous subtle template scope problems. +

    + + +

    6.18.8 More on templates

    + +

    If all of this isn't quite enough and you really want to make someone's head explode, SWIG directives such as @@ -3527,19 +3773,19 @@ included directly in template definitions. For example:

     // File : list.h
     template<class T> class List {
    -   ...
    +  ...
     public:
    -    %rename(__getitem__) get(int);
    -    List(int max);
    -    ~List();
    -    ...
    -    T get(int index);
    -    %extend {
    -        char *__str__() {
    -            /* Make a string representation */
    -            ...
    -        }
    +  %rename(__getitem__) get(int);
    +  List(int max);
    +  ~List();
    +  ...
    +  T get(int index);
    +  %extend {
    +    char *__str__() {
    +      /* Make a string representation */
    +      ...
         }
    +  }
     };
     
    @@ -3549,30 +3795,30 @@ instantiation.

    -It is also possible to separate these declarations from the template class. For example: +It is also possible to separate these declarations from the class template. For example:

     %rename(__getitem__) List::get;
     %extend List {
    -    char *__str__() {
    -        /* Make a string representation */
    -        ...
    -    }
    -    /* Make a copy */
    -    T *__copy__() {
    -       return new List<T>(*$self);
    -    }
    +  char *__str__() {
    +    /* Make a string representation */
    +    ...
    +  }
    +  /* Make a copy */
    +  T *__copy__() {
    +    return new List<T>(*$self);
    +  }
     };
     
     ...
     template<class T> class List {
    -    ...
    -    public:
    -    List() { }
    -    T get(int index);
    -    ...
    +  ...
    +  public:
    +  List() { }
    +  T get(int index);
    +  ...
     };
     
    @@ -3590,30 +3836,48 @@ additional methods to a specific instantiation. For example: %template(intList) List<int>; %extend List<int> { - void blah() { - printf("Hey, I'm an List<int>!\n"); - } + void blah() { + printf("Hey, I'm an List<int>!\n"); + } };

    -SWIG even supports overloaded templated functions. As usual the %template directive -is used to wrap templated functions. For example: +It is even possible to extend a class via %extend with template methods, for example:

    -template<class T> void foo(T x) { };
    -template<class T> void foo(T x, T y) { };
    +%include <std_string.i>
     
    -%template(foo) foo<int>;
    +%inline %{
    +class ExtendMe {
    +public:
    +  template <typename T>
    +  T do_stuff_impl(int a, T b, double d) {
    +    return b;
    +  }
    +};
    +%}
    +
    +%extend ExtendMe {
    +  template<typename T>
    +  T do_overloaded_stuff(T b) {
    +    return $self->do_stuff_impl(0, b, 4.0);
    +  }
    +}
    +%template(do_overloaded_stuff) ExtendMe::do_overloaded_stuff<std::string>;
    +%template(do_overloaded_stuff) ExtendMe::do_overloaded_stuff<double>;
     

    -This will generate two overloaded wrapper methods, the first will take a single integer as an argument -and the second will take two integer arguments. +The wrapped ExtendMe class will then have two (overloaded) methods called do_overloaded_stuff. +

    + +

    +Compatibility Note: Extending a class with template methods was added in version 3.0.12

    @@ -3638,20 +3902,20 @@ For example:

     template <class T> class OuterTemplateClass {};
     
    -// The nested class OuterClass::InnerClass inherits from the template class
    +// The nested class OuterClass::InnerClass inherits from the class template
     // OuterTemplateClass<OuterClass::InnerStruct> and thus the template needs
     // to be expanded with %template before the OuterClass declaration.
     %template(OuterTemplateClass_OuterClass__InnerStruct)
    -    OuterTemplateClass<OuterClass::InnerStruct>
    +  OuterTemplateClass<OuterClass::InnerStruct>
     
     
     // Don't forget to use %feature("flatnested") for OuterClass::InnerStruct and
     // OuterClass::InnerClass if the target language doesn't support nested classes.
     class OuterClass {
    -    public:
    -        // Forward declarations:
    -        struct InnerStruct;
    -        class InnerClass;
    +  public:
    +    // Forward declarations:
    +    struct InnerStruct;
    +    class InnerClass;
     };
     
     struct OuterClass::InnerStruct {};
    @@ -3680,7 +3944,7 @@ introduced a new class name.  This name could then be used with other directives
     
     %template(vectori) vector<int>;
     %extend vectori {
    -    void somemethod() { }
    +  void somemethod() { }
     };
     
    @@ -3694,7 +3958,7 @@ as the class name. For example:
     %template(vectori) vector<int>;
     %extend vector<int> {
    -    void somemethod() { }
    +  void somemethod() { }
     };
     
    @@ -3722,15 +3986,15 @@ encapsulate common functionality. For example:
     namespace math {
    -   double sin(double);
    -   double cos(double);
    +  double sin(double);
    +  double cos(double);
     
    -   class Complex {
    -      double im,re;
    -   public:
    -      ...
    -   };
    -   ...
    +  class Complex {
    +    double im, re;
    +  public:
    +    ...
    +  };
    +  ...
     };
     
    @@ -3798,18 +4062,18 @@ namespace A { } namespace B { - namespace C { - using namespace A; - } - typedef C::Foo FooClass; + namespace C { + using namespace A; + } + typedef C::Foo FooClass; } namespace BIGB = B; namespace D { - using BIGB::FooClass; - class Bar : public FooClass { - } + using BIGB::FooClass; + class Bar : public FooClass { + } }; class Spam : public D::Bar { @@ -3843,12 +4107,12 @@ you have code like this,
     %module foo
     namespace foo {
    -   void bar(int);
    -   void spam();
    +  void bar(int);
    +  void spam();
     }
     
     namespace bar {
    -   void blah();
    +  void blah();
     }
     
     
    @@ -3859,6 +4123,8 @@ then SWIG simply creates three wrapper functions bar(), spam(), and blah() in the target language. SWIG does not prepend the names with a namespace prefix nor are the functions packaged in any kind of nested scope. +Note that the default handling of flattening all the namespace scopes in the target language +can be changed via the nspace feature.

    @@ -3882,10 +4148,10 @@ namespaces to generate a name conflict in the target language. For example:

     namespace A {
    -   void foo(int);
    +  void foo(int);
     }
     namespace B {
    -   void foo(double);
    +  void foo(double);
     }
     
    @@ -3910,10 +4176,10 @@ To resolve this error, simply use %rename to disambiguate the declarati %rename(B_foo) B::foo; ... namespace A { - void foo(int); + void foo(int); } namespace B { - void foo(double); // Gets renamed to B_foo + void foo(double); // Gets renamed to B_foo }
    @@ -3932,7 +4198,7 @@ system to track type-names. Therefore, if you have code like this:
     namespace A {
    -   typedef int Integer;
    +  typedef int Integer;
     }
     using namespace A;
     void foo(Integer x);
    @@ -3953,7 +4219,7 @@ in a different namespace.  For example:
     
     namespace foo {
    -    template<typename T> T max(T a, T b) { return a > b ? a : b; }
    +  template<typename T> T max(T a, T b) { return a > b ? a : b; }
     }
     
     using foo::max;
    @@ -3962,8 +4228,8 @@ using foo::max;
     %template(maxfloat) foo::max<float>;    // Okay (qualified name).
     
     namespace bar {
    -    using namespace foo;
    -    %template(maxdouble)  max<double>;    // Okay.
    +  using namespace foo;
    +  %template(maxdouble)  max<double>;    // Okay.
     }
     
    @@ -3981,18 +4247,18 @@ typemaps, exception handlers, and so forth. For example, consider the following
     namespace foo {
    -    typedef int Integer;
    -    class bar {
    +  typedef int Integer;
    +  class bar {
         public:
    -       ...
    -    };
    +    ...
    +  };
     }
     
     %extend foo::bar {
    -   Integer add(Integer x, Integer y) {
    -       Integer r = x + y;        // Error. Integer not defined in this scope
    -       return r;
    -   }
    +  Integer add(Integer x, Integer y) {
    +    Integer r = x + y;        // Error. Integer not defined in this scope
    +    return r;
    +  }
     };
     
    @@ -4007,10 +4273,10 @@ To fix the problem, make sure you use fully qualified names. For example:
     %extend foo::bar {
    -   Integer add(Integer x, Integer y) {
    -       foo::Integer r = x + y;        // Ok.
    -       return r;
    -   }
    +  Integer add(Integer x, Integer y) {
    +    foo::Integer r = x + y;        // Ok.
    +    return r;
    +  }
     };
     
    @@ -4037,17 +4303,17 @@ these directives, consider the following: // Good version %inline %{ namespace foo { - void bar(int) { ... } - ... + void bar(int) { ... } + ... } %} // Bad version. Emitted code not placed in namespace. namespace foo { %inline %{ - void bar(int) { ... } /* I'm bad */ - ... -%} + void bar(int) { ... } /* I'm bad */ + ... + %} }
    @@ -4060,12 +4326,12 @@ included in the generated functions. For example, if you have code like this,
     namespace foo {
    -   class bar {
    -   public:
    -        %extend {
    -           int blah(int x);
    -        };
    -   };
    +  class bar {
    +    public:
    +      %extend {
    +        int blah(int x);
    +      };
    +  };
     }
     
    @@ -4088,13 +4354,13 @@ conflicts in the input, there will be no conflicts in the generated code.
     namespace foo {
    -   class bar;
    -   class spam {
    -   public:
    -        ...
    -        operator bar();      // Conversion of spam -> bar
    -        ...
    -   };
    +  class bar;
    +  class spam {
    +    public:
    +    ...
    +    operator bar();      // Conversion of spam -> bar
    +    ...
    +  };
     }
     
    @@ -4128,13 +4394,13 @@ Note, however, that if the operator is defined using a qualifier in its name, th %rename(tofoo) foo::spam::operator bar(); // will not match %rename(tofoo) foo::spam::operator foo::bar(); // will match namespace foo { - class bar; - class spam { - public: - ... - operator foo::bar(); - ... - }; + class bar; + class spam { + public: + ... + operator foo::bar(); + ... + }; } @@ -4147,9 +4413,7 @@ namespace foo {

    Note: The flattening of namespaces is only intended to serve as a basic namespace implementation. -None of the target language modules are currently programmed -with any namespace awareness. In the future, language modules may or may not provide -more advanced namespace support. +More advanced handling of namespaces is discussed next.

    6.19.1 The nspace feature for namespaces

    @@ -4245,9 +4509,9 @@ In the example below, the generic template type is used to rename to bbb
    -%rename(bbb) Space::ABC::aaa(T t);                  // will match but with lower precedence than ccc
    +%rename(bbb) Space::ABC::aaa(T t);                     // will match but with lower precedence than ccc
     %rename(ccc) Space::ABC<Space::XYZ>::aaa(Space::XYZ t);// will match but with higher precedence
    -                                                             // than bbb
    +                                                       // than bbb
     
     namespace Space {
       class XYZ {};
    @@ -4325,9 +4589,9 @@ class Error { };
     
     class Foo {
     public:
    -    ...
    -    void blah() throw(Error);
    -    ...
    +  ...
    +  void blah() throw(Error);
    +  ...
     };
     
    @@ -4345,14 +4609,14 @@ write code like this: f = Foo() try: f.blah() -except Error,e: - # e is a wrapped instance of "Error" +except Error, e: + # e is a wrapped instance of "Error"

    Details of how to tailor code for handling the caught C++ exception and converting it into the target language's exception/error handling mechanism -is outlined in the "throws" typemap section. +is outlined in the "throws" typemap section.

    @@ -4369,7 +4633,7 @@ The next section details a way of simulating an exception specification or repla Exceptions are automatically handled for methods with an exception specification. Similar handling can be achieved for methods without exception specifications through the %catches feature. It is also possible to replace any declared exception specification using the %catches feature. -In fact, %catches uses the same "throws" typemaps that SWIG uses for exception specifications in handling exceptions. +In fact, %catches uses the same "throws" typemaps that SWIG uses for exception specifications in handling exceptions. The %catches feature must contain a list of possible types that can be thrown. For each type that is in the list, SWIG will generate a catch handler, in the same way that it would for types declared in the exception specification. Note that the list can also include the catch all specification "...". @@ -4384,15 +4648,15 @@ struct Error2 : EBase { }; struct Error3 : EBase { }; struct Error4 : EBase { }; -%catches(Error1,Error2,...) Foo::bar(); +%catches(Error1, Error2, ...) Foo::bar(); %catches(EBase) Foo::blah(); class Foo { public: - ... - void bar(); - void blah() throw(Error1,Error2,Error3,Error4); - ... + ... + void bar(); + void blah() throw(Error1, Error2, Error3, Error4); + ... }; @@ -4422,9 +4686,9 @@ For example:

    -double do_op(Object *o, double (Object::*callback)(double,double));
    -extern double (Object::*fooptr)(double,double);
    -%constant double (Object::*FOO)(double,double) = &Object::foo;
    +double do_op(Object *o, double (Object::*callback)(double, double));
    +extern double (Object::*fooptr)(double, double);
    +%constant double (Object::*FOO)(double, double) = &Object::foo;
     
    @@ -4468,7 +4732,7 @@ for member pointers.

    In some C++ programs, objects are often encapsulated by smart-pointers or proxy classes. This is sometimes done to implement automatic memory management (reference counting) or -persistence. Typically a smart-pointer is defined by a template class where +persistence. Typically a smart-pointer is defined by a class template where the -> operator has been overloaded. This class is then wrapped around some other class. For example:

    @@ -4477,21 +4741,21 @@ around some other class. For example:
     // Smart-pointer class
     template<class T> class SmartPtr {
    -    T *pointee;
    +  T *pointee;
     public:
    -    SmartPtr(T *p) : pointee(p) { ... }
    -    T *operator->() {
    -        return pointee;
    -    }
    -    ...
    +  SmartPtr(T *p) : pointee(p) { ... }
    +  T *operator->() {
    +    return pointee;
    +  }
    +  ...
     };
     
     // Ordinary class
     class Foo_Impl {
     public:
    -    int x;
    -    virtual void bar();
    -    ...
    +  int x;
    +  virtual void bar();
    +  ...
     };
     
     // Smart-pointer wrapper
    @@ -4499,13 +4763,13 @@ typedef SmartPtr<Foo_Impl> Foo;
     
     // Create smart pointer Foo
     Foo make_Foo() {
    -    return SmartPtr<Foo_Impl>(new Foo_Impl());
    +  return SmartPtr<Foo_Impl>(new Foo_Impl());
     }
     
     // Do something with smart pointer Foo
     void do_something(Foo f) {
    -    printf("x = %d\n", f->x);
    -    f->bar();
    +  printf("x = %d\n", f->x);
    +  f->bar();
     }
     
     // Call the wrapped smart pointer proxy class in the target language 'Foo'
    @@ -4550,13 +4814,13 @@ code produces wrappers like this:
     
     int Foo_x_get(Foo *f) {
    -   return (*f)->x;
    +  return (*f)->x;
     }
     void Foo_x_set(Foo *f, int value) {
    -   (*f)->x = value;
    +  (*f)->x = value;
     }
     void Foo_bar(Foo *f) {
    -   (*f)->bar();
    +  (*f)->bar();
     }
     
    @@ -4604,13 +4868,13 @@ example, if you have this code

     class Foo {
     public:
    -    int x;
    +  int x;
     };
     
     class Bar {
     public:
    -    int x;       
    -    Foo *operator->();
    +  int x;       
    +  Foo *operator->();
     };
     
    @@ -4636,8 +4900,8 @@ class Foo { // Ignored class Bar { public: - Foo *operator->(); - ... + Foo *operator->(); + ... };
    @@ -4773,26 +5037,26 @@ For example:

    where the code passed to the "ref" and "unref" features will be -executed as needed whenever a new object is passed to python, or when -python tries to release the proxy object instance, respectively. +executed as needed whenever a new object is passed to Python, or when +Python tries to release the proxy object instance, respectively.

    -On the python side, the use of a reference counted object is no +On the Python side, the use of a reference counted object is no different to any other regular instance:

     def create_A():
    -  a = A()         # SWIG ref 'a' - new object is passed to python (count: 1)
    -  b1 = B(a)       # C++ ref 'a (count: 2)
    -  if 1 + 1 == 2:
    -     b2 = B(a)    # C++ ref 'a' (count: 3)
    -  return a        # 'b1' and 'b2' are released and deleted, C++ unref 'a' twice (count: 1)
    +    a = A()         # SWIG ref 'a' - new object is passed to Python (count: 1)
    +    b1 = B(a)       # C++ ref 'a (count: 2)
    +    if 1 + 1 == 2:
    +        b2 = B(a)   # C++ ref 'a' (count: 3)
    +    return a        # 'b1' and 'b2' are released and deleted, C++ unref 'a' twice (count: 1)
     
    -a = create_A()    # (count: 1)
    -exit              # 'a' is released, SWIG unref 'a' called in the destructor wrapper (count: 0)
    +a = create_A()      # (count: 1)
    +exit                # 'a' is released, SWIG unref 'a' called in the destructor wrapper (count: 0)
     
    @@ -4813,8 +5077,8 @@ features:

    In other words, SWIG will not do anything special when a new object -is passed to python, and it will always 'delete' the underlying object when -python releases the proxy instance. +is passed to Python, and it will always 'delete' the underlying object when +Python releases the proxy instance.

    @@ -4859,19 +5123,19 @@ base classes. For example:

     class Foo {
     public:
    -      int  blah(int x);
    +  int  blah(int x);
     };
     
     class Bar {
     public:
    -      double blah(double x);
    +  double blah(double x);
     };
     
     class FooBar : public Foo, public Bar {
     public:
    -      using Foo::blah;  
    -      using Bar::blah;
    -      char *blah(const char *x);
    +  using Foo::blah;
    +  using Bar::blah;
    +  char *blah(const char *x);
     };
     
    @@ -4914,14 +5178,14 @@ you wrap this code in Python, the module works just like you would expect:
     class Foo {
     protected:
    -    int x;
    -    int blah(int x);
    +  int x;
    +  int blah(int x);
     };
     
     class Bar : public Foo {
     public:
    -    using Foo::x;       // Make x public
    -    using Foo::blah;    // Make blah public
    +  using Foo::x;       // Make x public
    +  using Foo::blah;    // Make blah public
     };
     
    @@ -4952,14 +5216,14 @@ correctly, you can always change the interface to the following: class FooBar : public Foo, public Bar { public: #ifndef SWIG - using Foo::blah; - using Bar::blah; + using Foo::blah; + using Bar::blah; #else - int blah(int x); // explicitly tell SWIG about other declarations - double blah(double x); + int blah(int x); // explicitly tell SWIG about other declarations + double blah(double x); #endif - char *blah(const char *x); + char *blah(const char *x); }; @@ -4976,14 +5240,14 @@ won't cause a conflict. For example:

     class Foo {
     public:
    -       int blah(int );
    -       double blah(double);
    +  int blah(int );
    +  double blah(double);
     };
     
     class Bar : public Foo {
     public:
    -       using Foo::blah;    // Only imports blah(double);
    -       int blah(int);
    +  using Foo::blah;    // Only imports blah(double);
    +  int blah(int);
     };
     
    @@ -4997,14 +5261,14 @@ imported by using. For example: %rename(blah_long) Foo::blah(long); class Foo { public: - int blah(int); - long blah(long); // Renamed to blah_long + int blah(int); + long blah(long); // Renamed to blah_long }; class Bar : public Foo { public: - using Foo::blah; // Only imports blah(int) - double blah(double x); + using Foo::blah; // Only imports blah(int) + double blah(double x); }; @@ -5021,7 +5285,7 @@ normal classes.

    If the target language doesn't support nested classes directly, or the support is not implemented in the -language module (like for python currently), then the visible nested classes are moved to the same name +language module (like for Python currently), then the visible nested classes are moved to the same name space as the containing class (nesting hierarchy is "flattened"). The same behaviour may be turned on for C# and Java by the %feature ("flatnested"); If there is a class with the same name in the outer namespace the inner class (or the global one) may be renamed or ignored: @@ -5101,7 +5365,7 @@ void bar(Object *); ... // C++ code void blah() { - bar(foo()); // Error: bar discards const + bar(foo()); // Error: bar discards const }; @@ -5132,7 +5396,152 @@ using another tool if maintaining constness is the most important part of your project.

    -

    6.29 Where to go for more information

    +

    6.29 Callbacks to the target language

    + + +

    +C/C++ function pointers are often used for callbacks and this is discussed in the +Pointers to functions and callbacks section. +The callback techniques described therein provide a way to control callbacks to a C/C++ function but not callbacks into the target language. +The techniques described below show how the director feature can be used to support callbacks from C/C++ to the target language. +

    + +

    6.29.1 Introduction to director classes

    + + +

    +The director feature enables the ability for a target language class to derive from a wrapped C++ class. +The target language can override virtual methods of a wrapped C++ class, thereby supporting cross-language polymorphism. +Code can 'call up' from C++ into the target language by simply calling a virtual method overridden in a derived class in the target language. +The wrapped C++ classes that have this ability are termed 'director' classes. +The director feature is documented individually in each target language and the reader should locate and read this to obtain a full understanding of directors. +

    + +

    6.29.2 Using directors and target language callbacks

    + + +

    +SWIG's primary goal is to make it possible to call C/C++ code from a target language, however, the director feature enables the reverse. +While there isn't simple direct support for calling target language code from C, the director feature makes this possible. +It does require some work and additional wrapper code to be provided by the user. +The additional code required must be C++ and not C code and hence may introduce a small dependency on C++ if using a pure C project. +In a nutshell, the user must create a C++ base class and turn it into a director class. +A virtual method in the director base class is required. +SWIG generates the code to call up into the target language when wrapping the director virtual method. +

    + +

    +Let's look at some details next. +Consider the same function pointer for a callback called binary_op from the +Pointers to functions and callbacks section. +For completeness, the code required for the module and director feature is also shown: +

    + +
    +%module(directors="1") example
    +
    +%{
    +int binary_op(int a, int b, int (*op)(int, int)) {
    +  return op(a, b);
    +}
    +%}
    +
    + +

    +The goal is to have a target language function that gets called by binary_op. +The target language function should have the equivalent signature as the C/C++ function pointer int (*op)(int, int). +As we are using directors, we need a C++ virtual method with this signature, so let's +define the C++ class and pure virtual method first and make it a director class via the +director feature: +

    + +
    +%feature("director") BinaryOp;
    +
    +%inline %{
    +struct BinaryOp {
    +  virtual int handle(int a, int b) = 0;
    +  virtual ~BinaryOp() {}
    +};
    +%}
    +
    + +

    +The following handler_helper function and binary_op_wrapper function completes the code needed in the +C++/SWIG layer. The binary_op_wrapper function is wrapped by SWIG and is very similar to the binary_op function, +however, it takes a pointer to the director base class BinaryOp instead of a C/C++ function pointer. +

    + +
    +%{
    +static BinaryOp *handler_ptr = NULL;
    +static int handler_helper(int a, int b) {
    +  // Make the call up to the target language when handler_ptr
    +  // is an instance of a target language director class
    +  return handler_ptr->handle(a, b);
    +}
    +// If desired, handler_ptr above could be changed to a thread-local variable in order to make thread-safe
    +%}
    +
    +%inline %{
    +int binary_op_wrapper(int a, int b, BinaryOp *handler) {
    +  handler_ptr = handler;
    +  int result = binary_op(a, b, &handler_helper);
    +  handler = NULL;
    +  return result;
    +}
    +%}
    +
    + +

    +On the target language side, we need to derive a class from BinaryOp and override the +handle method. In Python this could be as simple as: +

    + +
    +
    +import example
    +
    +# PythonBinaryOp class is defined and derived from C++ class BinaryOp
    +class PythonBinaryOp(example.BinaryOp):
    +
    +    # Define Python class 'constructor'
    +    def __init__(self):
    +        # Call C++ base class constructor
    +        example.BinaryOp.__init__(self)
    +
    +    # Override C++ method: virtual int handle(int a, int b) = 0;
    +    def handle(self, a, b):
    +        # Return the product
    +        return a * b
    +
    +
    + +

    +For this to work from Python, an instance of the PythonBinaryOp class is created +and then passed to binary_op_wrapper. The net result is the binary_op +function will in turn be called which will call handler_helper which will call +the virtual handle method, that is, the Python method handle in the PythonBinaryOp class. The result will be the product of 10 and 20 and make its way back to Python and hence +200 will be printed with the following code: +

    + +
    +
    +handler = PythonBinaryOp()
    +result = example.binary_op_wrapper(10, 20, handler)
    +print result
    +
    +
    + +

    +This has thus demonstrated a C/C++ function pointer calling back into a target language function. +The code could be made a little more user friendly by using %rename to provide the +original binary_op name from the target language instead of binary_op_wrapper. +A C++ functor base class and Python functor class +could also be used instead, but these are left as exercises for the reader. +

    + +

    6.30 Where to go for more information

    diff --git a/Doc/Manual/Scilab.html b/Doc/Manual/Scilab.html index 0eaa61423..88ab8043e 100644 --- a/Doc/Manual/Scilab.html +++ b/Doc/Manual/Scilab.html @@ -9,7 +9,7 @@ -

    39 SWIG and Scilab

    +

    35 SWIG and Scilab

      @@ -39,7 +39,7 @@
  • Pointers
  • Structures @@ -88,11 +88,11 @@ This chapter explains how to use SWIG for Scilab. After this introduction, you s

    -

    39.1 Preliminaries

    +

    35.1 Preliminaries

    -SWIG for Scilab supports Linux. Other operating sytems haven't been tested. +SWIG for Scilab supports Linux. Other operating systems haven't been tested.

    @@ -105,7 +105,7 @@ SWIG for Scilab supports C language. C++ is partially supported. See 39.2 Running SWIG +

    35.2 Running SWIG

    @@ -121,15 +121,15 @@ In this example we bind from C a function and a global variable into Scilab. The double Foo = 3.0; int fact(int n) { - if (n < 0) { - return 0; - } - else if (n == 0) { - return 1; - } - else { - return n * fact(n-1); - } + if (n < 0) { + return 0; + } + else if (n == 0) { + return 1; + } + else { + return n * fact(n-1); + } } %}

  • @@ -139,7 +139,7 @@ Note: a code in an %inline section is both parsed and wrapped by SWIG,

    -

    39.2.1 Generating the module

    +

    35.2.1 Generating the module

    @@ -182,7 +182,7 @@ The swig executable has several other command line options you can use.

    -

    39.2.2 Building the module

    +

    35.2.2 Building the module

    @@ -202,7 +202,7 @@ $ gcc -shared example_wrap.o -o libexample.so Note: we supposed in this example that the path to the Scilab include directory is /usr/local/include/scilab (which is the case in a Debian environment), this should be changed for another environment.

    -

    39.2.3 Loading the module

    +

    35.2.3 Loading the module

    @@ -226,7 +226,7 @@ Link done. which means that Scilab has successfully loaded the shared library. The module functions and other symbols are now available in Scilab.

    -

    39.2.4 Using the module

    +

    35.2.4 Using the module

    @@ -260,7 +260,7 @@ ans = Note: for conciseness, we assume in the subsequent Scilab code examples that the modules have been beforehand built and loaded in Scilab.

    -

    39.2.5 Scilab command line options

    +

    35.2.5 Scilab command line options

    @@ -304,6 +304,11 @@ The following table lists the Scilab specific command line options in addition t Generate the gateway XML with the given <gateway_id> + +-targetversion +Generate for Scilab target (major) version + +

    @@ -315,10 +320,10 @@ $ swig -scilab -help -

    39.3 A basic tour of C/C++ wrapping

    +

    35.3 A basic tour of C/C++ wrapping

    -

    39.3.1 Overview

    +

    35.3.1 Overview

    @@ -327,18 +332,22 @@ This means that functions, structs, classes, variables, etc... are interfaced th There are a few exceptions, such as constants and enumerations, which can be wrapped directly as Scilab variables.

    -

    39.3.2 Identifiers

    +

    35.3.2 Identifiers

    -In Scilab 5.x, identifier names are composed of 24 characters maximum (this limitation should disappear from Scilab 6.0 onwards). -
    Thus long function or variable names may be truncated and this can cause ambiguities. +In Scilab 5.x, identifier names are composed of 24 characters maximum (this limitation disappears from Scilab 6.0 onwards). +
    By default, variable, member, and function names longer than 24 characters are truncated, and a warning is produced for each truncation.

    -

    This happens especially when wrapping structs/classes, for which the wrapped function name is composed of the struct/class name and field names. +

    This can cause ambiguities, especially when wrapping structs/classes, for which the wrapped function name is composed of the struct/class name and field names. In these cases, the %rename directive can be used to choose a different Scilab name.

    -

    39.3.3 Functions

    +

    +Note: truncations can be disabled by specifying the target version 6 of Scilab in the targetversion argument (i.e. -targetversion 6). +

    + +

    35.3.3 Functions

    @@ -369,7 +378,7 @@ ans = 24. -

    39.3.3.1 Argument passing

    +

    35.3.3.1 Argument passing

    @@ -422,7 +431,7 @@ In Scilab, parameters are passed by value. The output (and inout) parameters are 7. -

    39.3.3.2 Multiple output arguments

    +

    35.3.3.2 Multiple output arguments

    @@ -443,14 +452,15 @@ The example below shows this for a C function returning 2 values and a result: int divide(int n, int d, int *OUTPUT, int *OUTPUT); %{ -int divide(int n, int d, int q*, int *r) { - if (d != 0) { - *q = n / d; - *r = n % d; - return 1; - } - else return 0; -} + int divide(int n, int d, int q*, int *r) { + if (d != 0) { + *q = n / d; + *r = n % d; + return 1; + } else { + return 0; + } + } %} @@ -470,7 +480,7 @@ int divide(int n, int d, int q*, int *r) { -

    39.3.4 Global variables

    +

    35.3.4 Global variables

    @@ -539,10 +549,10 @@ It works the same:

    -

    39.3.5 Constants and enumerations

    +

    35.3.5 Constants and enumerations

    -

    39.3.5.1 Constants

    +

    35.3.5.1 Constants

    @@ -683,7 +693,7 @@ are mapped to Scilab variables, with the same name: 3.14 -

    39.3.5.2 Enumerations

    +

    35.3.5.2 Enumerations

    @@ -748,14 +758,14 @@ typedef enum { RED, BLUE, GREEN } color; -

    39.3.6 Pointers

    +

    35.3.6 Pointers

    Pointers are supported by SWIG. A pointer can be returned from a wrapped C/C++ function, stored in a Scilab variable, and used in input argument of another C/C++ function.

    -Also, thanks to the SWIG runtime which stores informations about types, pointer types are tracked between exchanges Scilab and the native code. Indeed pointer types are stored alongside the pointer adress. +Also, thanks to the SWIG runtime which stores information about types, pointer types are tracked between exchanges Scilab and the native code. Indeed pointer types are stored alongside the pointer address. A pointer is mapped to a Scilab structure (tlist), which contains as fields the pointer address and the pointer type (in fact a pointer to the type information structure in the SWIG runtime).
    Why a native pointer is not mapped to a Scilab pointer (type name: "pointer", type ID: 128) ? The big advantage of mapping to a tlist is that it exposes a new type for the pointer in Scilab, type which can be acessed in Scilab with the typeof function, and manipulated using the overloading mechanism. @@ -810,7 +820,7 @@ Note: the type name _p_FILE which means "pointer to FILE". The user of a pointer is responsible for freeing it or, like in the example, closing any resources associated with it (just as is required in a C program).

    -

    39.3.6.1 Utility functions

    +

    35.3.6.1 Utility functions

    @@ -851,7 +861,7 @@ ans = -

    39.3.6.2 Null pointers:

    +

    35.3.6.2 Null pointers:

    @@ -867,7 +877,7 @@ Using the previous SWIG_this() and SWIG_ptr(), it is possible -

    39.3.7 Structures

    +

    35.3.7 Structures

    @@ -886,8 +896,8 @@ Let's see it on an example of a struct with two members: %inline %{ typedef struct { - int x; - int arr[4]; + int x; + int arr[4]; } Foo; %} @@ -963,7 +973,7 @@ ans =

    -Note: the pointer to the struct works as described in Pointers. For example, the type of the struct pointer can be get with typeof, as following: +Note: the pointer to the struct works as described in Pointers. For example, the type of the struct pointer can be get with typeof, as following:

    @@ -976,7 +986,7 @@ Note: the pointer to the struct works as described in 39.3.8 C++ classes
    +

    35.3.8 C++ classes

    @@ -1027,7 +1037,7 @@ ans =

    -Note: like structs, class pointers are mapped as described in Pointers. Let's give an example which shows that each class pointer type is a new type in Scilab that can be used for example (through overloading) to implement a custom print for the Point class: +Note: like structs, class pointers are mapped as described in Pointers. Let's give an example which shows that each class pointer type is a new type in Scilab that can be used for example (through overloading) to implement a custom print for the Point class:

    @@ -1044,7 +1054,7 @@ Note: like structs, class pointers are mapped as described in 39.3.9 C++ inheritance
    +

    35.3.9 C++ inheritance

    @@ -1119,25 +1129,25 @@ But we can use either use the get_perimeter() function of the parent cl 18.84

    -

    39.3.10 C++ overloading

    +

    35.3.10 C++ overloading

    -As explained in 6.15 SWIG provides support for overloaded functions and constructors. +As explained in Overloaded functions and methods SWIG provides support for overloaded functions and constructors.

    -

    As SWIG knows pointer types, the overloading works also with pointer types, here is is an example with a function magnify overloaded for the previous classes Shape and Circle: +

    As SWIG knows pointer types, the overloading works also with pointer types, here is an example with a function magnify overloaded for the previous classes Shape and Circle:

     %module example
     
     void magnify(Square *square, double factor) {
    -    square->size *= factor;
    +  square->size *= factor;
     };
     
     void magnify(Circle *circle, double factor) {
    -    square->radius *= factor;
    +  square->radius *= factor;
     };
     
    @@ -1159,7 +1169,7 @@ void magnify(Circle *circle, double factor) { -

    39.3.11 Pointers, references, values, and arrays

    +

    35.3.11 Pointers, references, values, and arrays

    @@ -1217,7 +1227,7 @@ All these functions will return a pointer to an instance of Foo. As the function spam7 returns a value, new instance of Foo has to be allocated, and a pointer on this instance is returned.

    -

    39.3.12 C++ templates

    +

    35.3.12 C++ templates

    @@ -1242,7 +1252,7 @@ struct triplet { } }; -%template(IntTriplet) triplet<int,int,int>; +%template(IntTriplet) triplet<int, int, int>;

    @@ -1276,7 +1286,7 @@ Then in Scilab: More details on template support can be found in the templates documentation.

    -

    39.3.13 C++ operators

    +

    35.3.13 C++ operators

    @@ -1320,7 +1330,7 @@ private:

     --> c1 = new_Complex(3, 7);
     
    ---> c2 = Complex_plus(c, new_Complex(1,1));
    +--> c2 = Complex_plus(c, new_Complex(1, 1));
     
     --> Complex_toDouble(c2)
      ans  =
    @@ -1329,7 +1339,7 @@ private:
     
    -

    39.3.14 C++ namespaces

    +

    35.3.14 C++ namespaces

    @@ -1354,7 +1364,7 @@ namespace foo { } struct Vector { - double x,y,z; + double x, y, z; }; }; @@ -1407,7 +1417,7 @@ Note: the nspace feature is not supp

    -

    39.3.15 C++ exceptions

    +

    35.3.15 C++ exceptions

    @@ -1431,7 +1441,7 @@ void throw_exception() throw(char const *) {

     -->throw_exception()
       !--error 999
    -SWIG/Scilab: Exception (char const *) occured: Bye world !
    +SWIG/Scilab: Exception (char const *) occurred: Bye world !
     

    @@ -1448,7 +1458,7 @@ It can be used with the lasterror() function as following: --> lasterror() ans = - SWIG/Scilab: Exception (char const *) occured: Bye world ! + SWIG/Scilab: Exception (char const *) occurred: Bye world !

    @@ -1478,7 +1488,7 @@ void throw_stl_invalid_arg(int i) throw(std::invalid_argument) {

     --> throw_int();
                 !--error 999
    -SWIG/Scilab: Exception (int) occured: 12
    +SWIG/Scilab: Exception (int) occurred: 12
     
     -->throw_stl_invalid_arg(-1);
                               !--error 999
    @@ -1490,17 +1500,17 @@ More complex or custom exception types require specific exception typemaps to be
     See the SWIG C++ documentation for more details.
     

    -

    39.3.16 C++ STL

    +

    35.3.16 C++ STL

    The Standard Template Library (STL) is partially supported. See STL for more details.

    -

    39.4 Type mappings and libraries

    +

    35.4 Type mappings and libraries

    -

    39.4.1 Default primitive type mappings

    +

    35.4.1 Default primitive type mappings

    @@ -1551,7 +1561,7 @@ The default behaviour is for SWIG to generate code that will give a runtime erro -

    39.4.2 Arrays

    +

    35.4.2 Arrays

    @@ -1606,15 +1616,15 @@ void printArray(int values[], int len) { [ 0 1 2 3 ]

    -

    39.4.3 Pointer-to-pointers

    +

    35.4.3 Pointer-to-pointers

    -There are no specific typemaps for pointer-to-pointers, they are are mapped as pointers in Scilab. +There are no specific typemaps for pointer-to-pointers, they are mapped as pointers in Scilab.

    -Pointer-to-pointers are sometimes used to implement matrices in C. The following is a an example of this: +Pointer-to-pointers are sometimes used to implement matrices in C. The following is an example of this:

    @@ -1635,17 +1645,17 @@ double **create_matrix() { return M; } -// Gets the item M(i,j) value +// Gets the item M(i, j) value double get_matrix(double **M, int i, int j) { return M[i][j]; } -// Sets the item M(i,j) value to be val +// Sets the item M(i, j) value to be val void set_matrix(double **M, int i, int j, double val) { M[i][j] = val; } -// Prints a matrix (2,2) to console +// Prints a matrix (2, 2) to console void print_matrix(double **M, int nbRows, int nbCols) { int i, j; for (i = 0; i < 2; i++) { @@ -1679,7 +1689,7 @@ void print_matrix(double **M, int nbRows, int nbCols) { -

    39.4.4 Matrices

    +

    35.4.4 Matrices

    @@ -1768,11 +1778,11 @@ void absolute(int *matrix, int matrixNbRow, int matrixNbCol, The remarks made earlier for arrays also apply here:

      -
    • The values of matrices in Scilab are column-major orderered,
    • +
    • The values of matrices in Scilab are column-major orderered,
    • There is no control while converting double values to integers, double values are truncated without any checking or warning.
    -

    39.4.5 STL

    +

    35.4.5 STL

    @@ -1972,7 +1982,7 @@ ans = --> delete_PersonPtrSet(p); -

    39.5 Module initialization

    +

    35.5 Module initialization

    @@ -1996,7 +2006,7 @@ For example, to initialize the module example: --> example_Init(); -

    39.6 Building modes

    +

    35.6 Building modes

    @@ -2011,7 +2021,7 @@ To produce a dynamic module, when generating the wrapper, there are two possibil

  • the builder mode. In this mode, Scilab is responsible of building. -

    39.6.1 No-builder mode

    +

    35.6.1 No-builder mode

    @@ -2024,7 +2034,7 @@ This mode is the best option to use when you have to integrate the module build

    -

    39.6.2 Builder mode

    +

    35.6.2 Builder mode

    @@ -2052,7 +2062,7 @@ In this mode, the following SWIG options may be used to setup the build: Let's give an example how to build a module example, composed of two sources, and using a library dependency:

      -
    • the sources are baa1.c and baa2.c (and are stored in in the current directory)
    • +
    • the sources are baa1.c and baa2.c (and are stored in the current directory)
    • the library is libfoo in /opt/foo (headers stored in /opt/foo/include, and shared library in /opt/foo/lib)
    @@ -2061,17 +2071,17 @@ The command is:

    -$ swig -scilab -builder -buildercflags -I/opt/foo/include -builderldflags "-L/opt/foo/lib -lfoo" -buildersources baa1.cxx,baa2.cxx example.i
    +$ swig -scilab -builder -buildercflags -I/opt/foo/include -builderldflags "-L/opt/foo/lib -lfoo" -buildersources baa1.cxx, baa2.cxx example.i
     
    -

    39.7 Generated scripts

    +

    35.7 Generated scripts

    In this part we give some details about the generated Scilab scripts.

    -

    39.7.1 Builder script

    +

    35.7.1 Builder script

    @@ -2081,12 +2091,12 @@ In this part we give some details about the generated Scilab scripts. ilib_name = "examplelib"; files = ["example_wrap.c"]; libs = []; -table = ["fact","_wrap_fact";"Foo_set","_wrap_Foo_set";"Foo_get","_wrap_Foo_get";]; -ilib_build(ilib_name,table,files,libs); +table = ["fact", "_wrap_fact";"Foo_set", "_wrap_Foo_set";"Foo_get", "_wrap_Foo_get";]; +ilib_build(ilib_name, table, files, libs);

    -ilib_build(lib_name,table,files,libs) is used to create shared libraries, and to generate a loader file used to dynamically load the shared library into Scilab. +ilib_build(lib_name, table, files, libs) is used to create shared libraries, and to generate a loader file used to dynamically load the shared library into Scilab.

      @@ -2096,7 +2106,7 @@ ilib_build(ilib_name,table,files,libs);
    • table: two column string matrix containing a table of pairs of 'scilab function name', 'C function name'.
    -

    39.7.2 Loader script

    +

    35.7.2 Loader script

    @@ -2117,7 +2127,7 @@ list_functions = [ 'fact'; 'Foo_set'; 'Foo_get'; ]; -addinter(libexamplelib_path+'/libexamplelib.so','libexamplelib',list_functions); +addinter(libexamplelib_path+'/libexamplelib.so', 'libexamplelib', list_functions); // remove temp. variables on stack clear libexamplelib_path; clear list_functions; @@ -2126,7 +2136,7 @@ clear get_file_path;

    -addinter(files,spname,fcts) performs dynamic linking of a compiled C interface function. +addinter(files, spname, fcts) performs dynamic linking of a compiled C interface function.

    • files: a character string or a vector of character strings defining the object files (containing the C interface functions) to link with.
    • @@ -2135,7 +2145,7 @@ clear get_file_path;
    -

    39.8 Other resources

    +

    35.8 Other resources

    -

    Language Module Documentation

    +

    Supported Language Modules Documentation

    +

    Experimental Language Modules Documentation

    + + +

    Developer Documentation

      diff --git a/Doc/Manual/Tcl.html b/Doc/Manual/Tcl.html index 31fae0321..ba5ca3852 100644 --- a/Doc/Manual/Tcl.html +++ b/Doc/Manual/Tcl.html @@ -7,7 +7,7 @@ -

      40 SWIG and Tcl

      +

      36 SWIG and Tcl

      -

      40.3.2 Functions

      +

      36.3.2 Functions

      @@ -711,7 +711,7 @@ like you think it does: % -

      40.3.3 Global variables

      +

      36.3.3 Global variables

      @@ -791,7 +791,7 @@ extern char *path; // Read-only (due to %immutable) -

      40.3.4 Constants and enums

      +

      36.3.4 Constants and enums

      @@ -837,8 +837,8 @@ access constants in procedure bodies. For example:

       proc blah {} {
      -   global FOO
      -   bar $FOO
      +  global FOO
      +  bar $FOO
       }
       
      @@ -865,7 +865,7 @@ its actual value or a symbolic identifier name. For example:
       proc blah {} {
      -   bar FOO
      +  bar FOO
       }
       
      @@ -875,7 +875,7 @@ When an identifier name is given, it is used to perform an implicit hash-table l conversion. This allows the global statement to be omitted.

      -

      40.3.5 Pointers

      +

      36.3.5 Pointers

      @@ -949,16 +949,16 @@ example: %inline %{ /* C-style cast */ Bar *FooToBar(Foo *f) { - return (Bar *) f; + return (Bar *) f; } /* C++-style cast */ Foo *BarToFoo(Bar *b) { - return dynamic_cast<Foo*>(b); + return dynamic_cast<Foo*>(b); } Foo *IncrFoo(Foo *f, int i) { - return f+i; + return f+i; } %} @@ -971,7 +971,7 @@ C-style cast may return a bogus result whereas as the C++-style cast will return None if the conversion can't be performed.

      -

      40.3.6 Structures

      +

      36.3.6 Structures

      @@ -981,7 +981,7 @@ This provides a very natural interface. For example,

       struct Vector {
      -  double x,y,z;
      +  double x, y, z;
       };
       
       
      @@ -1028,12 +1028,12 @@ can also be forced to be read-only using the %immutable directive. For
       struct Foo {
      -   ...
      -   %immutable;
      -   int x;        /* Read-only members */
      -   char *name;
      -   %mutable;
      -   ...
      +  ...
      +  %immutable;
      +  int x;        /* Read-only members */
      +  char *name;
      +  %mutable;
      +  ...
       };
       
      @@ -1054,7 +1054,7 @@ example, consider this:
       struct Bar {
      -    int  x[16];
      +  int  x[16];
       };
       
      @@ -1100,11 +1100,11 @@ pointer. For example, suppose you have two structures like this:
       struct Foo {
      -   int a;
      +  int a;
       };
       
       struct Bar {
      -   Foo f;
      +  Foo f;
       };
       
      @@ -1253,7 +1253,7 @@ Note: Tcl only destroys the underlying object if it has ownership. See the memory management section that appears shortly.

      -

      40.3.7 C++ classes

      +

      36.3.7 C++ classes

      @@ -1302,9 +1302,8 @@ To illustrate, suppose you have a class like this:

       class Spam {
       public:
      -   static void foo();
      -   static int bar;
      -
      +  static void foo();
      +  static int bar;
       };
       
      @@ -1320,7 +1319,7 @@ In Tcl, the static member is accessed as follows: -

      40.3.8 C++ inheritance

      +

      36.3.8 C++ inheritance

      @@ -1369,7 +1368,7 @@ For instance: It is safe to use multiple inheritance with SWIG.

      -

      40.3.9 Pointers, references, values, and arrays

      +

      36.3.9 Pointers, references, values, and arrays

      @@ -1423,7 +1422,7 @@ to hold the result and a pointer is returned (Tcl will release this memory when the return value is garbage collected).

      -

      40.3.10 C++ overloaded functions

      +

      36.3.10 C++ overloaded functions

      @@ -1457,9 +1456,9 @@ Similarly, if you have a class like this,

       class Foo {
       public:
      -    Foo();
      -    Foo(const Foo &);
      -    ...
      +  Foo();
      +  Foo(const Foo &);
      +  ...
       };
       
      @@ -1546,7 +1545,7 @@ first declaration takes precedence. Please refer to the "SWIG and C++" chapter for more information about overloading.

      -

      40.3.11 C++ operators

      +

      36.3.11 C++ operators

      @@ -1648,7 +1647,7 @@ There are ways to make this operator appear as part of the class using the % Keep reading.

      -

      40.3.12 C++ namespaces

      +

      36.3.12 C++ namespaces

      @@ -1662,10 +1661,10 @@ submodules or packages. For example, if you have a file like this, %module example namespace foo { - int fact(int n); - struct Vector { - double x,y,z; - }; + int fact(int n); + struct Vector { + double x, y, z; + }; }; @@ -1694,11 +1693,11 @@ For example: %rename(Bar_spam) Bar::spam; namespace Foo { - int spam(); + int spam(); } namespace Bar { - int spam(); + int spam(); } @@ -1712,7 +1711,7 @@ utilizes thousands of small deeply nested namespaces each with identical symbol names, well, then you get what you deserve.

      -

      40.3.13 C++ templates

      +

      36.3.13 C++ templates

      @@ -1731,16 +1730,16 @@ For example: template<class T1, class T2> struct pair { - typedef T1 first_type; - typedef T2 second_type; - T1 first; - T2 second; - pair(); - pair(const T1&, const T2&); + typedef T1 first_type; + typedef T2 second_type; + T1 first; + T2 second; + pair(); + pair(const T1&, const T2&); ~pair(); }; -%template(pairii) pair<int,int>; +%template(pairii) pair<int, int>; @@ -1764,7 +1763,7 @@ More details can be found in the SWIG and C++ -

      40.3.14 C++ Smart Pointers

      +

      36.3.14 C++ Smart Pointers

      @@ -1776,9 +1775,9 @@ that implements operator->() like this:

       template<class T> class SmartPtr {
      -   ...
      -   T *operator->();
      -   ...
      +  ...
      +  T *operator->();
      +  ...
       }
       
      @@ -1791,8 +1790,8 @@ Then, if you have a class like this,
       class Foo {
       public:
      -     int x;
      -     int bar();
      +  int x;
      +  int bar();
       };
       
      @@ -1848,7 +1847,7 @@ simply use the __deref__() method. For example: -

      40.4 Further details on the Tcl class interface

      +

      36.4 Further details on the Tcl class interface

      @@ -1861,7 +1860,7 @@ of low-level details were omitted. This section provides a brief overview of how the proxy classes work.

      -

      40.4.1 Proxy classes

      +

      36.4.1 Proxy classes

      @@ -1874,9 +1873,9 @@ have a class like this

       class Foo {
       public:
      -     int x;
      -     int spam(int);
      -     ...
      +  int x;
      +  int spam(int);
      +  ...
       
      @@ -1887,19 +1886,19 @@ then SWIG transforms it into a set of low-level procedural wrappers. For example
       Foo *new_Foo() {
      -    return new Foo();
      +  return new Foo();
       }
       void delete_Foo(Foo *f) {
      -    delete f;
      +  delete f;
       }
       int Foo_x_get(Foo *f) {
      -    return f->x;
      +  return f->x;
       }
       void Foo_x_set(Foo *f, int value) {
      -    f->x = value;
      +  f->x = value;
       }
       int Foo_spam(Foo *f, int arg1) {
      -    return f->spam(arg1);
      +  return f->spam(arg1);
       }
       
      @@ -1926,7 +1925,7 @@ function. This allows objects to be encapsulated objects that look a lot like as shown in the last section.

      -

      40.4.2 Memory management

      +

      36.4.2 Memory management

      @@ -1946,8 +1945,8 @@ ownership of the result. For example:

       class Foo {
       public:
      -    Foo();
      -    Foo bar();
      +  Foo();
      +  Foo bar();
       };
       
      @@ -1976,9 +1975,9 @@ they came from. Therefore, the ownership is set to zero. For example:
       class Foo {
       public:
      -    ...
      -    Foo *spam();
      -    ...
      +  ...
      +  Foo *spam();
      +  ...
       };
       
      @@ -2012,8 +2011,8 @@ or global variable. For example, consider this interface: %module example struct Foo { - int value; - Foo *next; + int value; + Foo *next; }; Foo *head = 0; @@ -2065,10 +2064,10 @@ change the ownership of an object. For instance, consider code like this:
       class Node {
      -   Object *value;
      +  Object *value;
       public:
      -   void set_value(Object *v) { value = v; }
      -   ...
      +  void set_value(Object *v) { value = v; }
      +  ...
       };
       
      @@ -2114,7 +2113,7 @@ typemaps--an advanced topic discussed later.

      -

      40.5 Input and output parameters

      +

      36.5 Input and output parameters

      @@ -2125,7 +2124,7 @@ example:

       void add(int x, int y, int *result) {
      -   *result = x + y;
      +  *result = x + y;
       }
       
      @@ -2137,7 +2136,7 @@ or perhaps
       int sub(int *x, int *y) {
      -   return *x+*y;
      +  return *x+*y;
       }
       
      @@ -2198,7 +2197,7 @@ If a function mutates one of its parameters like this,
       void negate(int *x) {
      -   *x = -(*x);
      +  *x = -(*x);
       }
       
      @@ -2302,7 +2301,7 @@ set c [lindex $dim 1] -

      40.6 Exception handling

      +

      36.6 Exception handling

      @@ -2328,7 +2327,7 @@ class DoubleArray { } // Destroy an array ~DoubleArray() { - delete ptr; + delete ptr; } // Return the length of the array int length() { @@ -2436,7 +2435,7 @@ Since SWIG's exception handling is user-definable, you are not limited to C++ ex See the chapter on "Customization Features" for more examples.

      -

      40.7 Typemaps

      +

      36.7 Typemaps

      @@ -2453,7 +2452,7 @@ Typemaps are only used if you want to change some aspect of the primitive C-Tcl interface.

      -

      40.7.1 What is a typemap?

      +

      36.7.1 What is a typemap?

      @@ -2466,9 +2465,9 @@ you might define a typemap like this: %module example %typemap(in) int { - if (Tcl_GetIntFromObj(interp,$input,&$1) == TCL_ERROR) - return TCL_ERROR; - printf("Received an integer : %d\n",$1); + if (Tcl_GetIntFromObj(interp, $input, &$1) == TCL_ERROR) + return TCL_ERROR; + printf("Received an integer : %d\n", $1); } %inline %{ extern int fact(int n); @@ -2505,9 +2504,9 @@ You can refine this by supplying an optional parameter name. For example: %module example %typemap(in) int n { - if (Tcl_GetIntFromObj(interp,$input,&$1) == TCL_ERROR) + if (Tcl_GetIntFromObj(interp, $input, &$1) == TCL_ERROR) return TCL_ERROR; - printf("n = %d\n",$1); + printf("n = %d\n", $1); } %inline %{ extern int fact(int n); @@ -2529,9 +2528,9 @@ the typemap system follows typedef declarations. For example:

       %typemap(in) int n {
      -  if (Tcl_GetIntFromObj(interp,$input,&$1) == TCL_ERROR)
      +  if (Tcl_GetIntFromObj(interp, $input, &$1) == TCL_ERROR)
           return TCL_ERROR;
      -  printf("n = %d\n",$1);
      +  printf("n = %d\n", $1);
       }
       %inline %{
       typedef int Integer;
      @@ -2553,7 +2552,7 @@ Typemaps can also be defined for groups of consecutive arguments.  For example:
       
       %typemap(in) (char *str, int len) {
      -    $1 = Tcl_GetStringFromObj($input,&$2);
      +    $1 = Tcl_GetStringFromObj($input, &$2);
       };
       
       int count(char c, char *str, int len);
      @@ -2573,7 +2572,7 @@ parameter is omitted):
       
      -

      40.7.2 Tcl typemaps

      +

      36.7.2 Tcl typemaps

      @@ -2586,7 +2585,7 @@ like this:

       %typemap(out) int {
      -    Tcl_SetObjResult(interp,Tcl_NewIntObj($1));
      +  Tcl_SetObjResult(interp, Tcl_NewIntObj($1));
       }
       
      @@ -2711,7 +2710,7 @@ Initialize an argument to a value before any conversions occur. Examples of these methods will appear shortly.

      -

      40.7.3 Typemap variables

      +

      36.7.3 Typemap variables

      @@ -2782,7 +2781,7 @@ properly assigned. The Tcl name of the wrapper function being created.

      -

      40.7.4 Converting a Tcl list to a char **

      +

      36.7.4 Converting a Tcl list to a char **

      @@ -2797,36 +2796,36 @@ used as a char ** object. // This tells SWIG to treat char ** as a special case %typemap(in) char ** { - Tcl_Obj **listobjv; - int nitems; - int i; - if (Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) { - return TCL_ERROR; - } - $1 = (char **) malloc((nitems+1)*sizeof(char *)); - for (i = 0; i < nitems; i++) { - $1[i] = Tcl_GetStringFromObj(listobjv[i],0); - } - $1[i] = 0; + Tcl_Obj **listobjv; + int nitems; + int i; + if (Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) { + return TCL_ERROR; + } + $1 = (char **) malloc((nitems+1)*sizeof(char *)); + for (i = 0; i < nitems; i++) { + $1[i] = Tcl_GetStringFromObj(listobjv[i], 0); + } + $1[i] = 0; } // This gives SWIG some cleanup code that will get called after the function call %typemap(freearg) char ** { - if ($1) { - free($1); - } + if ($1) { + free($1); + } } // Now a test functions %inline %{ -int print_args(char **argv) { + int print_args(char **argv) { int i = 0; while (argv[i]) { - printf("argv[%d] = %s\n", i,argv[i]); - i++; + printf("argv[%d] = %s\n", i, argv[i]); + i++; } return i; -} + } %} %include "tclsh.i" @@ -2844,7 +2843,7 @@ argv[2] = Larry 3 -

      40.7.5 Returning values in arguments

      +

      36.7.5 Returning values in arguments

      @@ -2855,21 +2854,21 @@ function argument. For example :

       // A typemap defining how to return an argument by appending it to the result
       %typemap(argout) double *outvalue {
      -     Tcl_Obj *o = Tcl_NewDoubleObj($1);
      -     Tcl_ListObjAppendElement(interp,$result,o);
      +  Tcl_Obj *o = Tcl_NewDoubleObj($1);
      +  Tcl_ListObjAppendElement(interp, $result, o);
       }
       
       // A typemap telling SWIG to ignore an argument for input
       // However, we still need to pass a pointer to the C function
      -%typemap(in,numinputs=0) double *outvalue (double temp) {
      -     $1 = &temp;
      +%typemap(in, numinputs=0) double *outvalue (double temp) {
      +  $1 = &temp;
       }
       
       // Now a function returning two values
       int mypow(double a, double b, double *outvalue) {
      -        if ((a < 0) || (b < 0)) return -1;
      -        *outvalue = pow(a,b);
      -        return 0;
      +  if ((a < 0) || (b < 0)) return -1;
      +  *outvalue = pow(a, b);
      +  return 0;
       };
       
      @@ -2886,7 +2885,7 @@ result, a Tcl function using these typemaps will work like this : % -

      40.7.6 Useful functions

      +

      36.7.6 Useful functions

      @@ -2962,7 +2961,7 @@ int Tcl_IsShared(Tcl_Obj *obj); -

      40.7.7 Standard typemaps

      +

      36.7.7 Standard typemaps

      @@ -2992,7 +2991,7 @@ work)

       %typemap(out) int, short, long {
      -   Tcl_SetIntObj($result,(int) $1);
      +  Tcl_SetIntObj($result, (int) $1);
       }
       
      @@ -3004,10 +3003,10 @@ work)
       %typemap(in) float, double {
      -   double temp;
      -   if (Tcl_GetDoubleFromObj(interp, $input, &temp) == TCL_ERROR)
      -       return TCL_ERROR;
      -   $1 = ($1_ltype) temp;
      +  double temp;
      +  if (Tcl_GetDoubleFromObj(interp, $input, &temp) == TCL_ERROR)
      +    return TCL_ERROR;
      +  $1 = ($1_ltype) temp;
       }
       
      @@ -3017,7 +3016,7 @@ work)
       %typemap(out) float, double {
      -   Tcl_SetDoubleObj($result, $1);
      +  Tcl_SetDoubleObj($result, $1);
       }
       
      @@ -3029,9 +3028,8 @@ work)
       %typemap(in) char * {
      -   int len;
      -   $1 = Tcl_GetStringFromObj(interp, &len);
      -   }
      +  int len;
      +  $1 = Tcl_GetStringFromObj(interp, &len);
       }
       
      @@ -3040,14 +3038,14 @@ work)
      -%typemap(out,noblock=1,fragment="SWIG_FromCharPtr") char *, const char * {
      -  Tcl_SetObjResult(interp,SWIG_FromCharPtr((const char *)$1));
      +%typemap(out, noblock=1, fragment="SWIG_FromCharPtr") char *, const char * {
      +  Tcl_SetObjResult(interp, SWIG_FromCharPtr((const char *)$1));
       }
       
       
      -

      40.7.8 Pointer handling

      +

      36.7.8 Pointer handling

      @@ -3090,7 +3088,9 @@ is usually accessed as follows:

       Foo *f;
      -if (SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0) == -1) return NULL;
      +if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0))) {
      +  SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
      +}
       
       Tcl_Obj *;
       obj = SWIG_NewPointerObj(f, SWIGTYPE_p_Foo, 0);
      @@ -3105,7 +3105,9 @@ variable $1_descriptor.  For example:
       
       %typemap(in) Foo * {
      -   if ((SWIG_ConvertPtr($input,(void **) &$1, $1_descriptor,0)) == -1) return NULL;
      +  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
      +    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
      +  }
       }
       
      @@ -3118,12 +3120,14 @@ For example:
       %typemap(in) Foo * {
      -   if ((SWIG_ConvertPtr($input,(void **) &$1, $descriptor(Foo *), 0)) == -1) return NULL;
      +  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $descriptor(Foo *), 0))) {
      +    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
      +  }
       }
       
      -

      40.8 Turning a SWIG module into a Tcl Package.

      +

      36.8 Turning a SWIG module into a Tcl Package.

      @@ -3195,7 +3199,7 @@ As a final note, most SWIG examples do not yet use the to use the load command instead.

      -

      40.9 Building new kinds of Tcl interfaces (in Tcl)

      +

      36.9 Building new kinds of Tcl interfaces (in Tcl)

      @@ -3211,28 +3215,28 @@ helper functions to access arrays : %inline %{ double *new_double(int size) { - return (double *) malloc(size*sizeof(double)); + return (double *) malloc(size*sizeof(double)); } void delete_double(double *a) { - free(a); + free(a); } double get_double(double *a, int index) { - return a[index]; + return a[index]; } void set_double(double *a, int index, double val) { - a[index] = val; + a[index] = val; } int *new_int(int size) { - return (int *) malloc(size*sizeof(int)); + return (int *) malloc(size*sizeof(int)); } void delete_int(int *a) { - free(a); + free(a); } int get_int(int *a, int index) { - return a[index]; + return a[index]; } int set_int(int *a, int index, int val) { - a[index] = val; + a[index] = val; } %} @@ -3294,7 +3298,7 @@ danger of blowing something up (although it is easily accomplished with an out of bounds array access).

      -

      40.9.1 Proxy classes

      +

      36.9.1 Proxy classes

      @@ -3415,7 +3419,7 @@ short, but clever Tcl script can be combined with SWIG to do many interesting things.

      -

      40.10 Tcl/Tk Stubs

      +

      36.10 Tcl/Tk Stubs

      diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index b074e9f94..8a31dbf10 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -7,7 +7,7 @@ -

      11 Typemaps

      +

      13 Typemaps

    • Some typemap examples
        @@ -88,6 +89,9 @@
      • Usage
    • Typemaps and overloading +
    • More about %apply and %clear
    • Passing data between typemaps
    • C++ "this" pointer @@ -98,7 +102,7 @@ -

      11.1 Introduction

      +

      13.1 Introduction

      @@ -115,7 +119,7 @@ to re-read the earlier chapters if you have found your way to this chapter with only a vague idea of what SWIG already does by default.

      -

      11.1.1 Type conversion

      +

      13.1.1 Type conversion

      @@ -163,16 +167,16 @@ Inside the wrapper function, you might see these functions used like this:

       PyObject *wrap_factorial(PyObject *self, PyObject *args) {
      -    int       arg1;
      -    int       result;
      -    PyObject *obj1;
      -    PyObject *resultobj;
      +  int       arg1;
      +  int       result;
      +  PyObject *obj1;
      +  PyObject *resultobj;
       
      -    if (!PyArg_ParseTuple("O:factorial", &obj1)) return NULL;
      -    arg1 = PyInt_AsLong(obj1);
      -    result = factorial(arg1);
      -    resultobj = PyInt_FromLong(result);
      -    return resultobj;
      +  if (!PyArg_ParseTuple("O:factorial", &obj1)) return NULL;
      +  arg1 = PyInt_AsLong(obj1);
      +  result = factorial(arg1);
      +  resultobj = PyInt_FromLong(result);
      +  return resultobj;
       }
       
      @@ -208,7 +212,7 @@ to read the extension documentation for your favorite language to know how it works (an exercise left to the reader).

      -

      11.1.2 Typemaps

      +

      13.1.2 Typemaps

      @@ -221,12 +225,12 @@ a special %typemap directive is used. For example:

       /* Convert from Python --> C */
       %typemap(in) int {
      -    $1 = PyInt_AsLong($input);
      +  $1 = PyInt_AsLong($input);
       }
       
       /* Convert from C --> Python */
       %typemap(out) int {
      -    $result = PyInt_FromLong($1);
      +  $result = PyInt_FromLong($1);
       }
       
    • @@ -269,33 +273,33 @@ A wrapper function would look approximately like this:
       PyObject *wrap_gcd(PyObject *self, PyObject *args) {
      -   int arg1;
      -   int arg2;
      -   int result;
      -   PyObject *obj1;
      -   PyObject *obj2;
      -   PyObject *resultobj;
      +  int arg1;
      +  int arg2;
      +  int result;
      +  PyObject *obj1;
      +  PyObject *obj2;
      +  PyObject *resultobj;
       
      -   if (!PyArg_ParseTuple("OO:gcd", &obj1, &obj2)) return NULL;
      +  if (!PyArg_ParseTuple("OO:gcd", &obj1, &obj2)) return NULL;
       
      -   /* "in" typemap, argument 1 */   
      -   {
      -      arg1 = PyInt_AsLong(obj1);
      -   }
      +  /* "in" typemap, argument 1 */
      +  {
      +    arg1 = PyInt_AsLong(obj1);
      +  }
       
      -   /* "in" typemap, argument 2 */
      -   {
      -      arg2 = PyInt_AsLong(obj2);
      -   }
      +  /* "in" typemap, argument 2 */
      +  {
      +    arg2 = PyInt_AsLong(obj2);
      +  }
       
      -   result = gcd(arg1,arg2);
      +  result = gcd(arg1, arg2);
       
      -   /* "out" typemap, return value */
      -   {
      -      resultobj = PyInt_FromLong(result);
      -   }
      +  /* "out" typemap, return value */
      +  {
      +    resultobj = PyInt_FromLong(result);
      +  }
       
      -   return resultobj;
      +  return resultobj;
       }
       
      @@ -309,7 +313,7 @@ parts of the generated wrapper functions. Because arbitrary code can be insert possible to completely change the way in which values are converted.

      -

      11.1.3 Pattern matching

      +

      13.1.3 Pattern matching

      @@ -322,7 +326,7 @@ it is applied to all future occurrences of that type in the input file. For exa

       /* Convert from Perl --> C */
       %typemap(in) int {
      -   $1 = SvIV($input);
      +  $1 = SvIV($input);
       }
       
       ...
      @@ -343,12 +347,12 @@ underlying type.  For example, you could have code like this:
       
       /* Convert from Ruby--> C */
       %typemap(in) int {
      -   $1 = NUM2INT($input);
      +  $1 = NUM2INT($input);
       }
       ...
       typedef int Integer;
       namespace foo {
      -    typedef Integer Number;
      +  typedef Integer Number;
       };
       
       int foo(int x);
      @@ -360,7 +364,7 @@ int spam(foo::Number a, foo::Number b);
       

      In this case, the typemap is still applied to the proper arguments even though typenames don't always match the text "int". This ability to track types is a critical part of SWIG--in fact, all -of the target language modules work merely define a set of typemaps for the basic types. Yet, it +of the target language modules work merely define a family of typemaps for the basic types. Yet, it is never necessary to write new typemaps for typenames introduced by typedef.

      @@ -372,11 +376,11 @@ example, you could write a typemap like this:
       %typemap(in) double nonnegative {
      -   $1 = PyFloat_AsDouble($input);
      -   if ($1 < 0) {
      -        PyErr_SetString(PyExc_ValueError,"argument must be nonnegative.");
      -        return NULL;
      -   }
      +  $1 = PyFloat_AsDouble($input);
      +  if ($1 < 0) {
      +    PyErr_SetString(PyExc_ValueError, "argument must be nonnegative.");
      +    SWIG_fail;
      +  }
       }
       
       ...
      @@ -398,8 +402,8 @@ consecutive arguments.    For example:
       
       %typemap(in) (char *str, int len) {
      -    $1 = PyString_AsString($input);   /* char *str */
      -    $2 = PyString_Size($input);       /* int len   */
      +  $1 = PyString_AsString($input);   /* char *str */
      +  $2 = PyString_Size($input);       /* int len   */
       }
       ...
       int count(char *str, int len, char c);
      @@ -411,7 +415,7 @@ In this case, a single input object is expanded into a pair of C arguments.  Thi
       provides a hint to the unusual variable naming scheme involving $1, $2, and so forth.
       

      -

      11.1.4 Reusing typemaps

      +

      13.1.4 Reusing typemaps

      @@ -427,21 +431,43 @@ be copied and reused. One way to do this is to use assignment like this:

      -A more general form of copying is found in the %apply directive like this: +There is a more powerful way to copy a family of typemaps though. +Consider the following family of two typemap methods, "in" and "out" for type int:

       %typemap(in) int {
      -   /* Convert an integer argument */
      -   ...
      +  /* Convert an integer argument */
      +  ...
       }
       %typemap(out) int {
      -   /* Return an integer value */
      -   ...
      +  /* Return an integer value */
      +  ...
       }
      +
      +
      -/* Apply all of the integer typemaps to size_t */ +

      +Each of the two typemap methods could be copied individually for type size_t as follows: +

      + +
      +
      +/* Apply all of the int typemaps to size_t */
      +%typemap(in) size_t = int;   
      +%typemap(out) size_t = int;   
      +
      +
      + +

      +A more powerful form of copying is available from the %apply directive. +The code below is identical to the above: +

      + +
      +
      +/* Apply all of the int typemaps to size_t */
       %apply int { size_t };    
       
      @@ -467,7 +493,7 @@ typedef int size_t; then SWIG already knows that the int typemaps apply. You don't have to do anything.

      -

      11.1.5 What can be done with typemaps?

      +

      13.1.5 What can be done with typemaps?

      @@ -488,7 +514,7 @@ int foo(int x, double y, char *s);

      • Input argument conversion ("in" typemap).
      • -
      • Input argument type checking ("typecheck" typemap).
      • +
      • Input argument type checking for types used in overloaded methods ("typecheck" typemap).
      • Output argument handling ("argout" typemap).
      • Input argument value checking ("check" typemap).
      • Input argument initialization ("arginit" typemap).
      • @@ -548,7 +574,7 @@ int foo(int x, double y, char *s);
         struct Foo {
        -    int x[20];
        +  int x[20];
         };
         
        @@ -579,7 +605,7 @@ typemaps that expand upon this list. For example, the Java module defines a var aspects of the Java bindings. Consult language specific documentation for further details.

        -

        11.1.6 What can't be done with typemaps?

        +

        13.1.6 What can't be done with typemaps?

        @@ -622,7 +648,7 @@ function like this:

        -foo("hello",3)          # Reversed arguments
        +foo("hello", 3)          # Reversed arguments
         
        @@ -636,18 +662,18 @@ function instead. For example: %rename(foo) wrap_foo; %inline %{ void wrap_foo(char *s, int x) { - foo(x,s); + foo(x, s); } %}
      -

      11.1.7 Similarities to Aspect Oriented Programming

      +

      13.1.7 Similarities to Aspect Oriented Programming

      -SWIG has parallels to Aspect Oriented Software Development (AOP). -The AOP terminology with respect to SWIG typemaps can be viewed as follows: +SWIG has parallels to Aspect Oriented Software Development (AOP). +The AOP terminology with respect to SWIG typemaps can be viewed as follows:

      • Cross-cutting concerns: The cross-cutting concerns are the modularization of the functionality that the typemaps implement, which is primarily marshalling of types from/to the target language and C/C++. @@ -660,7 +686,7 @@ SWIG can also be viewed as has having a second set of aspects based around %exception are also cross-cutting concerns as they encapsulate code that can be used to add logging or exception handling to any function.

        -

        11.1.8 The rest of this chapter

        +

        13.1.8 The rest of this chapter

        @@ -680,14 +706,14 @@ of "The C Programming Language" by Kernighan and Ritchie or "The C++ Programming Language" by Stroustrup before going any further.

        -

        11.2 Typemap specifications

        +

        13.2 Typemap specifications

        This section describes the behavior of the %typemap directive itself.

        -

        11.2.1 Defining a typemap

        +

        13.2.1 Defining a typemap

        @@ -758,39 +784,39 @@ Here are some examples of valid typemap specifications:

         /* Simple typemap declarations */
         %typemap(in) int {
        -   $1 = PyInt_AsLong($input);
        +  $1 = PyInt_AsLong($input);
         }
         %typemap(in) int "$1 = PyInt_AsLong($input);";
         %typemap(in) int %{ 
        -   $1 = PyInt_AsLong($input);
        +  $1 = PyInt_AsLong($input);
         %}
         
         /* Typemap with extra argument name */
         %typemap(in) int nonnegative {
        -   ...
        +  ...
         }
         
         /* Multiple types in one typemap */
         %typemap(in) int, short, long { 
        -   $1 = SvIV($input);
        +  $1 = SvIV($input);
         }
         
         /* Typemap with modifiers */
        -%typemap(in,doc="integer") int "$1 = scm_to_int($input);";
        +%typemap(in, doc="integer") int "$1 = scm_to_int($input);";
         
         /* Typemap applied to patterns of multiple arguments */
         %typemap(in) (char *str, int len),
                      (char *buffer, int size)
         {
        -   $1 = PyString_AsString($input);
        -   $2 = PyString_Size($input);
        +  $1 = PyString_AsString($input);
        +  $2 = PyString_Size($input);
         }
         
         /* Typemap with extra pattern parameters */
         %typemap(in, numinputs=0) int *output (int temp),
                                   long *output (long temp)
         {
        -   $1 = &temp;
        +  $1 = &temp;
         }
         
      @@ -800,7 +826,7 @@ Admittedly, it's not the most readable syntax at first glance. However, the pur individual pieces will become clear.

      -

      11.2.2 Typemap scope

      +

      13.2.2 Typemap scope

      @@ -836,7 +862,7 @@ subject to the typemap rules that are in effect at the point where the class its

       class Foo {
      -   ...
      +  ...
       };
       
       %typemap(in) int {
      @@ -844,13 +870,13 @@ class Foo {
       }
       
       %extend Foo {
      -   int blah(int x);    // typemap has no effect.  Declaration is attached to Foo which 
      -                       // appears before the %typemap declaration.
      +  int blah(int x);    // typemap has no effect.  Declaration is attached to Foo which
      +                      // appears before the %typemap declaration.
       };
       
      -

      11.2.3 Copying a typemap

      +

      13.2.3 Copying a typemap

      @@ -908,40 +934,41 @@ The patterns for %apply follow the same rules as for %typemap. -

      11.2.4 Deleting a typemap

      +

      13.2.4 Deleting a typemap

      -A typemap can be deleted by simply defining no code. For example: +A particular typemap can be deleted / cleared by simply defining no code. For example:

      -%typemap(in) int;               // Clears typemap for int
      -%typemap(in) int, long, short;  // Clears typemap for int, long, short
      +%typemap(in) int;                 // Clears the "in" typemap for int
      +%typemap(in) int, long, short;    // Clears the "in" typemap for int, long, short
       %typemap(in) int *output;       
       

      -The %clear directive clears all typemaps for a given type. +The above syntax deletes a typemap for just one typemap method - the "in" method in each of the examples above. +The %clear directive is more powerful and will delete / clear a family of typemaps, that is, all the typemap methods for a given type. For example:

      -%clear int;                     // Removes all types for int
      +%clear int;                       // Delete all typemaps ("in", "out", "varin", ...) for int
       %clear int *output, long *output;
       

      Note: Since SWIG's default behavior is defined by typemaps, clearing a fundamental type like -int will make that type unusable unless you also define a new set of typemaps immediately +int will make that type unusable unless you also define a new family of typemaps immediately after the clear operation.

      -

      11.2.5 Placement of typemaps

      +

      13.2.5 Placement of typemaps

      @@ -952,22 +979,22 @@ example:

       %typemap(in) int {
      -   ...
      +  ...
       }
       
       namespace std {
      -    class string;
      -    %typemap(in) string {
      -        ...
      -    }
      +  class string;
      +  %typemap(in) string {
      +    ...
      +  }
       }
       
       class Bar {
       public:
      -    typedef const int & const_reference;
      -    %typemap(out) const_reference {
      -         ...
      -    }
      +  typedef const int & const_reference;
      +  %typemap(out) const_reference {
      +    ...
      +  }
       };
       
      @@ -981,10 +1008,10 @@ code
       namespace std {
      -    class string;
      -    %typemap(in) string {
      -       ...
      -    }
      +  class string;
      +  %typemap(in) string {
      +    ...
      +  }
       }
       
      @@ -996,17 +1023,17 @@ is really defining a typemap for the type std::string. You could have
       namespace std {
      -    class string;
      -    %typemap(in) string {          /* std::string */
      -       ...
      -    }
      +  class string;
      +  %typemap(in) string {          /* std::string */
      +    ...
      +  }
       }
       
       namespace Foo {
      -    class string;
      -    %typemap(in) string {          /* Foo::string */
      -       ...
      -    }
      +  class string;
      +  %typemap(in) string {          /* Foo::string */
      +    ...
      +  }
       }
       
      @@ -1021,7 +1048,7 @@ It should be noted that for scoping to work, SWIG has to know that stringclass string.

      -

      11.3 Pattern matching rules

      +

      13.3 Pattern matching rules

      @@ -1029,7 +1056,7 @@ The section describes the pattern matching rules by which C/C++ datatypes are as The matching rules can be observed in practice by using the debugging options also described.

      -

      11.3.1 Basic matching rules

      +

      13.3.1 Basic matching rules

      @@ -1095,23 +1122,23 @@ shows how some of the basic rules are applied:

       %typemap(in) int *x {
      -   ... typemap 1
      +  ... typemap 1
       }
       
       %typemap(in) int * {
      -   ... typemap 2
      +  ... typemap 2
       }
       
       %typemap(in) const int *z {
      -   ... typemap 3
      +  ... typemap 3
       }
       
       %typemap(in) int [4] {
      -   ... typemap 4
      +  ... typemap 4
       }
       
       %typemap(in) int [ANY] {
      -   ... typemap 5
      +  ... typemap 5
       }
       
       void A(int *x);        // int *x rule       (typemap 1)
      @@ -1128,7 +1155,7 @@ void F(int x[1000]);   // int [ANY] rule    (typemap 5)
       stripped all qualifiers in one step.
       

      -

      11.3.2 Typedef reductions matching

      +

      13.3.2 Typedef reductions matching

      @@ -1140,7 +1167,7 @@ for the reduced type. To illustrate, suppose you had code like this:

       %typemap(in) int {
      -   ... typemap 1
      +  ... typemap 1
       }
       
       typedef int Integer;
      @@ -1184,11 +1211,11 @@ typedef double  pdouble;     // Positive double
       
       // typemap 1
       %typemap(in) double {
      -   ... get a double ...
      +  ... get a double ...
       }
       // typemap 2
       %typemap(in) pdouble {
      -   ... get a positive double ...
      +  ... get a positive double ...
       }
       double sin(double x);           // typemap 1
       pdouble sqrt(pdouble x);        // typemap 2
      @@ -1247,7 +1274,7 @@ like this:
       
       typedef int Integer;
      -typedef foo<Integer,Integer> fooii;
      +typedef foo<Integer, Integer> fooii;
       void blah(fooii *x);
       
      @@ -1261,9 +1288,9 @@ In this case, the following typemap patterns are searched for the argument f fooii *x fooii * -# Reduce fooii --> foo<Integer,Integer> -foo<Integer,Integer> *x -foo<Integer,Integer> * +# Reduce fooii --> foo<Integer, Integer> +foo<Integer, Integer> *x +foo<Integer, Integer> * # Reduce Integer -> int foo<int, Integer> *x @@ -1278,7 +1305,7 @@ foo<int, int> *

      Typemap reductions are always applied to the left-most type that appears. Only when no reductions can be made to the left-most type are reductions made to other parts of the type. This behavior means that you could define a typemap for -foo<int,Integer>, but a typemap for foo<Integer,int> would never be matched. Admittedly, this +foo<int, Integer>, but a typemap for foo<Integer, int> would never be matched. Admittedly, this is rather esoteric--there's little practical reason to write a typemap quite like that. Of course, you could rely on this to confuse your coworkers even more.

      @@ -1303,7 +1330,7 @@ void go(Struct aStruct);
      -

      11.3.3 Default typemap matching rules

      +

      13.3.3 Default typemap matching rules

      @@ -1356,7 +1383,7 @@ Below is a list of the typical default types supplied by language modules, showi %typemap(in) SWIGTYPE * { ... default pointer handling ... }; %typemap(in) SWIGTYPE *const { ... default pointer const handling ... }; %typemap(in) SWIGTYPE *const& { ... default pointer const reference handling ... }; -%typemap(in) SWIGTYPE[ANY] { ... 1D fixed size arrays handlling ... }; +%typemap(in) SWIGTYPE[ANY] { ... 1D fixed size arrays handling ... }; %typemap(in) SWIGTYPE [] { ... unknown sized array handling ... }; %typemap(in) enum SWIGTYPE { ... default handling for enum values ... }; %typemap(in) const enum SWIGTYPE & { ... default handling for const enum reference values ... }; @@ -1441,7 +1468,7 @@ Finally the best way to view the typemap matching rules in action is via the -

      11.3.4 Multi-arguments typemaps

      +

      13.3.4 Multi-arguments typemaps

      @@ -1452,11 +1479,11 @@ any typemaps specified for a single type. For example:

       %typemap(in) (char *buffer, int len) {
      -   // typemap 1
      +  // typemap 1
       }
       
       %typemap(in) char *buffer {
      -   // typemap 2
      +  // typemap 2
       }
       
       void foo(char *buffer, int len, int count); // (char *buffer, int len)
      @@ -1471,7 +1498,7 @@ but all subsequent arguments must match exactly.
       

      -

      11.3.5 Matching rules compared to C++ templates

      +

      13.3.5 Matching rules compared to C++ templates

      @@ -1630,7 +1657,7 @@ are similar to those for specialized template handling.

      -

      11.3.6 Debugging typemap pattern matching

      +

      13.3.6 Debugging typemap pattern matching

      @@ -1713,7 +1740,7 @@ you'll find the full typemap contents (example shown below for Python):

       %typemap(in, noblock=1) SWIGTYPE [] (void *argp = 0, int res = 0) {
      -  res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown |  0 );
      +  res = SWIG_ConvertPtr($input, &argp, $descriptor, $disown |  0 );
         if (!SWIG_IsOK(res)) { 
           SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument "
                              "$argnum"" of type '" "$type""'"); 
      @@ -1735,7 +1762,7 @@ SWIGINTERN PyObject *_wrap_foo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
         void *argp1 = 0 ;
         int res1 = 0 ;
       ...
      -  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_a_4__int, 0 |  0 );
      +  res1 = SWIG_ConvertPtr(obj0, &argp1, SWIGTYPE_p_a_4__int, 0 |  0 );
         if (!SWIG_IsOK(res1)) {
           SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "foo" "', argument "
                              "1"" of type '" "int [10][4]""'"); 
      @@ -1757,7 +1784,7 @@ For example, the output for the code in the char const * and
       
       
    -

    11.4 Code generation rules

    +

    13.4 Code generation rules

    @@ -1851,7 +1878,7 @@ This section describes rules by which typemap code is inserted into the generated wrapper code.

    -

    11.4.1 Scope

    +

    13.4.1 Scope

    @@ -1861,7 +1888,7 @@ When a typemap is defined like this:

     %typemap(in) int {
    -   $1 = PyInt_AsLong($input);
    +  $1 = PyInt_AsLong($input);
     }
     
    @@ -1874,12 +1901,12 @@ wrapper code will look like this:
     wrap_whatever() {
    -    ...
    -    // Typemap code
    -    {                    
    -       arg1 = PyInt_AsLong(obj1);
    -    }
    -    ...
    +  ...
    +  // Typemap code
    +  {
    +    arg1 = PyInt_AsLong(obj1);
    +  }
    +  ...
     }
     
    @@ -1892,11 +1919,11 @@ for use during typemap execution. For example:
     %typemap(in) short {
    -   long temp;          /* Temporary value */
    -   if (Tcl_GetLongFromObj(interp, $input, &temp) != TCL_OK) {
    -      return TCL_ERROR;
    -   }
    -   $1 = (short) temp;
    +  long temp;          /* Temporary value */
    +  if (Tcl_GetLongFromObj(interp, $input, &temp) != TCL_OK) {
    +    return TCL_ERROR;
    +  }
    +  $1 = (short) temp;
     }
     
    @@ -1929,7 +1956,7 @@ a block scope when it is emitted. This sometimes results in a less complicated Note that only the third of the three typemaps have the typemap code passed through the SWIG preprocessor.

    -

    11.4.2 Declaring new local variables

    +

    13.4.2 Declaring new local variables

    @@ -1965,11 +1992,11 @@ then pass a pointer to the object. To do this, simply specify the typemap with

     %typemap(in) std::string * (std::string temp) {
    -    unsigned int len;
    -    char        *s;
    -    s = SvPV($input,len);         /* Extract string data */
    -    temp.assign(s,len);           /* Assign to temp */
    -    $1 = &temp;                   /* Set argument to point to temp */
    +  unsigned int len;
    +  char        *s;
    +  s = SvPV($input, len);         /* Extract string data */
    +  temp.assign(s, len);           /* Assign to temp */
    +  $1 = &temp;                   /* Set argument to point to temp */
     }
     
    @@ -1982,16 +2009,16 @@ the scope of the entire wrapper function. For example:
     wrap_foo() {
    -   std::string temp;    <--- Declaration of temp goes here
    -   ...
    +  std::string temp;    <--- Declaration of temp goes here
    +  ...
     
    -   /* Typemap code */
    -   {
    -      ...
    -      temp.assign(s,len);
    -      ...
    -   } 
    -   ...
    +  /* Typemap code */
    +  {
    +    ...
    +    temp.assign(s, len);
    +    ...
    +  }
    +  ...
     }
     
    @@ -2020,35 +2047,35 @@ generated code would actually look like this:
     wrap_foo() {
    -   int *arg1;    /* Actual arguments */
    -   int *arg2;
    -   int *arg3;
    -   std::string temp1;    /* Locals declared in the typemap */
    -   std::string temp2;
    -   std::string temp3;
    -   ...
    -   {
    -       char *s;
    -       unsigned int len;
    -       ...
    -       temp1.assign(s,len);
    -       arg1 = *temp1;
    -   }
    -   {
    -       char *s;
    -       unsigned int len;
    -       ...
    -       temp2.assign(s,len);
    -       arg2 = &temp2;
    -   }
    -   {
    -       char *s;
    -       unsigned int len;
    -       ...
    -       temp3.assign(s,len);
    -       arg3 = &temp3;
    -   }
    -   ...
    +  int *arg1;    /* Actual arguments */
    +  int *arg2;
    +  int *arg3;
    +  std::string temp1;    /* Locals declared in the typemap */
    +  std::string temp2;
    +  std::string temp3;
    +  ...
    +  {
    +    char *s;
    +    unsigned int len;
    +    ...
    +    temp1.assign(s, len);
    +    arg1 = *temp1;
    +  }
    +  {
    +    char *s;
    +    unsigned int len;
    +    ...
    +    temp2.assign(s, len);
    +    arg2 = &temp2;
    +  }
    +  {
    +    char *s;
    +    unsigned int len;
    +    ...
    +    temp3.assign(s, len);
    +    arg3 = &temp3;
    +  }
    +  ...
     }
     
    @@ -2096,7 +2123,7 @@ each type must have its own local variable declaration. -

    11.4.3 Special variables

    +

    13.4.3 Special variables

    @@ -2236,7 +2263,7 @@ This is useful when a typemap might match multiple C datatype. For example:

     %typemap(in)  int, short, long {
    -   $1 = ($1_ltype) PyInt_AsLong($input);
    +  $1 = ($1_ltype) PyInt_AsLong($input);
     }
     
    @@ -2284,8 +2311,8 @@ If necessary, type related substitutions can also be used when declaring locals.
     %typemap(in) int * ($*1_type temp) {
    -    temp = PyInt_AsLong($input);
    -    $1 = &temp;
    +  temp = PyInt_AsLong($input);
    +  $1 = &temp;
     }
     
    @@ -2299,7 +2326,7 @@ kinds of pointers. For example, if you wrote this,
     %typemap(in) int [10][20] {
    -   $1_ltype temp;
    +  $1_ltype temp;
     }
     
    @@ -2325,10 +2352,10 @@ casts to get the correct type when needed. For example:
     %typemap(in) int [10][20] {
    -   void *temp;
    -   ...
    -   (($1_ltype) temp)[i][j] = x;    /* set a value */
    -   ...
    +  void *temp;
    +  ...
    +  (($1_ltype) temp)[i][j] = x;    /* set a value */
    +  ...
     }
     
    @@ -2340,15 +2367,15 @@ Another approach, which only works for arrays is to use the $1_basetype
     %typemap(in) int [10][20] {
    -   $1_basetype temp[10][20];
    -   ...
    -   temp[i][j] = x;    /* set a value */
    -   ...
    +  $1_basetype temp[10][20];
    +  ...
    +  temp[i][j] = x;    /* set a value */
    +  ...
     }
     
    -

    11.4.4 Special variable macros

    +

    13.4.4 Special variable macros

    @@ -2360,7 +2387,7 @@ it is done during the SWIG parsing/compilation stages. The following special variable macros are available across all language modules.

    -

    11.4.4.1 $descriptor(type)

    +

    13.4.4.1 $descriptor(type)

    @@ -2371,7 +2398,7 @@ For example, $descriptor(std::vector<int> *) will expand into Run-time type checker usage section.

    -

    11.4.4.2 $typemap(method, typepattern)

    +

    13.4.4.2 $typemap(method, typepattern)

    @@ -2429,7 +2456,7 @@ The result is the following expansion -

    11.4.5 Special variables and typemap attributes

    +

    13.4.5 Special variables and typemap attributes

    @@ -2456,7 +2483,7 @@ is equivalent to the following as $*1_ltype expands to unsigned int -

    11.4.6 Special variables combined with special variable macros

    +

    13.4.6 Special variables combined with special variable macros

    @@ -2498,15 +2525,15 @@ which then expands to: -

    11.5 Common typemap methods

    +

    13.5 Common typemap methods

    -The set of typemaps recognized by a language module may vary. However, +The family of typemaps recognized by a language module may vary. However, the following typemap methods are nearly universal:

    -

    11.5.1 "in" typemap

    +

    13.5.1 "in" typemap

    @@ -2517,7 +2544,7 @@ to C. For example:

     %typemap(in) int {
    -   $1 = PyInt_AsLong($input);
    +  $1 = PyInt_AsLong($input);
     }
     
    @@ -2547,7 +2574,7 @@ specified. The numinputs attributes facilitates this. For example:
     // Ignored argument.
     %typemap(in, numinputs=0) int *out (int temp) {
    -    $1 = &temp;
    +  $1 = &temp;
     }
     
    @@ -2566,7 +2593,7 @@ Usually numinputs is not specified, whereupon the default value is 1, t is the same as the old "ignore" typemap.

    -

    11.5.2 "typecheck" typemap

    +

    13.5.2 "typecheck" typemap

    @@ -2576,8 +2603,8 @@ to see whether or not it matches a specific type. For example:

    -%typemap(typecheck,precedence=SWIG_TYPECHECK_INTEGER) int {
    -   $1 = PyInt_Check($input) ? 1 : 0;
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int {
    +  $1 = PyInt_Check($input) ? 1 : 0;
     }
     
    @@ -2585,6 +2612,7 @@ to see whether or not it matches a specific type. For example:

    For typechecking, the $1 variable is always a simple integer that is set to 1 or 0 depending on whether or not the input argument is the correct type. +Set to 1 if the input argument is the correct type otherwise set to 0.

    @@ -2592,7 +2620,7 @@ If you define new "in" typemaps and your program uses overloaded method "typecheck" typemaps. More details about this follow in the Typemaps and overloading section.

    -

    11.5.3 "out" typemap

    +

    13.5.3 "out" typemap

    @@ -2603,7 +2631,7 @@ into the target language. For example:

     %typemap(out) int {
    -   $result = PyInt_FromLong($1);
    +  $result = PyInt_FromLong($1);
     }
     
    @@ -2623,7 +2651,7 @@ $symname - Name of function/method being wrapped The "out" typemap supports an optional attribute flag called "optimal". This is for code optimisation and is detailed in the Optimal code generation when returning by value section.

    -

    11.5.4 "arginit" typemap

    +

    13.5.4 "arginit" typemap

    @@ -2637,12 +2665,12 @@ For example:

     // Set argument to NULL before any conversion occurs
     %typemap(arginit) int *data {
    -   $1 = NULL;
    +  $1 = NULL;
     }
     
    -

    11.5.5 "default" typemap

    +

    13.5.5 "default" typemap

    @@ -2653,7 +2681,7 @@ argument. For example:

     %typemap(default) int flags {
    -   $1 = DEFAULT_FLAGS;
    +  $1 = DEFAULT_FLAGS;
     }
     ...
     int foo(int x, int y, int flags);
    @@ -2675,7 +2703,7 @@ See the Default/optional arguments sec
     for further information on default argument wrapping.
     

    -

    11.5.6 "check" typemap

    +

    13.5.6 "check" typemap

    @@ -2687,14 +2715,14 @@ converted. For example:

     %typemap(check) int positive {
    -   if ($1 <= 0) {
    -       SWIG_exception(SWIG_ValueError,"Expected positive value.");
    -   }
    +  if ($1 <= 0) {
    +    SWIG_exception(SWIG_ValueError, "Expected positive value.");
    +  }
     }
     
    -

    11.5.7 "argout" typemap

    +

    13.5.7 "argout" typemap

    @@ -2708,12 +2736,12 @@ with an "in" typemap---possibly to ignore the input value. For example:

     /* Set the input argument to point to a temporary variable */
     %typemap(in, numinputs=0) int *out (int temp) {
    -   $1 = &temp;
    +  $1 = &temp;
     }
     
     %typemap(argout) int *out {
    -   // Append output value $1 to $result
    -   ...
    +  // Append output value $1 to $result
    +  ...
     }
     
    @@ -2740,7 +2768,7 @@ return values are often appended to return value of the function. See the typemaps.i library file for examples.

    -

    11.5.8 "freearg" typemap

    +

    13.5.8 "freearg" typemap

    @@ -2755,12 +2783,12 @@ For example:

     // Get a list of integers
     %typemap(in) int *items {
    -   int nitems = Length($input);    
    -   $1 = (int *) malloc(sizeof(int)*nitems);
    +  int nitems = Length($input);
    +  $1 = (int *) malloc(sizeof(int)*nitems);
     }
     // Free the list 
     %typemap(freearg) int *items {
    -   free($1);
    +  free($1);
     }
     
    @@ -2773,7 +2801,7 @@ be used in other typemaps whenever a wrapper function needs to abort prematurely.

    -

    11.5.9 "newfree" typemap

    +

    13.5.9 "newfree" typemap

    @@ -2785,10 +2813,10 @@ of a function. For example:

     %typemap(newfree) string * {
    -   delete $1;
    +  delete $1;
     }
     %typemap(out) string * {
    -   $result = PyString_FromString($1->c_str());
    +  $result = PyString_FromString($1->c_str());
     }
     ...
     
    @@ -2802,7 +2830,46 @@ string *foo();
     See Object ownership and %newobject for further details.
     

    -

    11.5.10 "memberin" typemap

    +

    13.5.10 "ret" typemap

    + + +

    +The "ret" typemap is not used very often, but can be useful for anything associated with +the return type, such as resource management, return value error checking, etc. +Usually this can all be done in the "out" typemap, but sometimes it is handy to use the +"out" typemap code untouched and add to the generated code using the code in the "ret" typemap. +One such case is memory clean up. For example, a stringheap_t type is defined indicating +that the returned memory must be deleted and a string_t type is defined indicating +that the returned memory must not be deleted. +

    + +
    +
    +%typemap(ret) stringheap_t %{
    +  free($1);
    +%}
    +
    +typedef char * string_t;
    +typedef char * stringheap_t;
    +
    +string_t MakeString1();
    +stringheap_t MakeString2();
    +
    +
    + +

    +The "ret" typemap above will only be used for MakeString2, but both functions +will use the default "out" typemap for char * provided by SWIG. +The code above would ensure the appropriate memory is freed in all target languages as the need +to provide custom "out" typemaps (which involve target language specific code) is not necessary. +

    + +

    +This approach is an alternative to using the "newfree" typemap and %newobject as there +is no need to list all the functions that require the memory cleanup, it is purely done on types. +

    + +

    13.5.11 "memberin" typemap

    @@ -2814,7 +2881,7 @@ cases. For example:

     %typemap(memberin) int [4] {
    -   memmove($1, $input, 4*sizeof(int));
    +  memmove($1, $input, 4*sizeof(int));
     }
     
    @@ -2824,7 +2891,7 @@ It is rarely necessary to write "memberin" typemaps---SWIG already provides a default implementation for arrays, strings, and other objects.

    -

    11.5.11 "varin" typemap

    +

    13.5.12 "varin" typemap

    @@ -2832,7 +2899,7 @@ The "varin" typemap is used to convert objects in the target language to C for t purposes of assigning to a C/C++ global variable. This is implementation specific.

    -

    11.5.12 "varout" typemap

    +

    13.5.13 "varout" typemap

    @@ -2840,11 +2907,11 @@ The "varout" typemap is used to convert a C/C++ object to an object in the targe language when reading a C/C++ global variable. This is implementation specific.

    -

    11.5.13 "throws" typemap

    +

    13.5.14 "throws" typemap

    -The "throws" typemap is only used when SWIG parses a C++ method with an exception specification or has the %catches feature attached to the method. +The "throws" typemap is only used when SWIG parses a C++ method with an exception specification or has the %catches feature attached to the method (see Exception handling with %catches). It provides a default mechanism for handling C++ methods that have declared the exceptions they will throw. The purpose of this typemap is to convert a C++ exception into an error or exception in the target language. It is slightly different to the other typemaps as it is based around the exception type rather than the type of a parameter or variable. @@ -2857,36 +2924,40 @@ For example: PyErr_SetString(PyExc_RuntimeError, $1); SWIG_fail; %} -void bar() throw (const char *); + +// Either an exception specification on the method + void bar() throw (const char *); + +// Or a %catches feature attached to the method + %catches(const char *) bar(); + void bar();

    -As can be seen from the generated code below, SWIG generates an exception handler -with the catch block comprising the "throws" typemap content. +As can be seen from the resulting generated code below, SWIG generates an exception handler +when wrapping the bar function with the catch block comprising the "throws" typemap content.

     ...
     try {
    -    bar();
    -}
    -catch(char const *_e) {
    -    PyErr_SetString(PyExc_RuntimeError, _e);
    -    SWIG_fail;
    -    
    +  bar();
    +} catch(char const *_e) {
    +  PyErr_SetString(PyExc_RuntimeError, _e);
    +  SWIG_fail;
     }
     ...
     

    -Note that if your methods do not have an exception specification yet they do throw exceptions, SWIG cannot know how to deal with them. -For a neat way to handle these, see the Exception handling with %exception section. +Note that if your methods do not have an exception specification but they do throw exceptions and you are not using %catches, SWIG cannot know how to deal with them. +Please also see the Exception handling with %exception section for another way to handle exceptions.

    -

    11.6 Some typemap examples

    +

    13.6 Some typemap examples

    @@ -2894,7 +2965,7 @@ This section contains a few examples. Consult language module documentation for more examples.

    -

    11.6.1 Typemaps for arrays

    +

    13.6.1 Typemaps for arrays

    @@ -2923,20 +2994,20 @@ similar to this: %typemap(in) float value[4] (float temp[4]) { int i; if (!PySequence_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a sequence"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Expected a sequence"); + SWIG_fail; } if (PySequence_Length($input) != 4) { - PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected 4 elements"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Size mismatch. Expected 4 elements"); + SWIG_fail; } for (i = 0; i < 4; i++) { - PyObject *o = PySequence_GetItem($input,i); + PyObject *o = PySequence_GetItem($input, i); if (PyNumber_Check(o)) { temp[i] = (float) PyFloat_AsDouble(o); } else { - PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Sequence elements must be numbers"); + SWIG_fail; } } $1 = temp; @@ -2968,20 +3039,20 @@ If you wanted to generalize the typemap to apply to arrays of all dimensions you %typemap(in) float value[ANY] (float temp[$1_dim0]) { int i; if (!PySequence_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a sequence"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Expected a sequence"); + SWIG_fail; } if (PySequence_Length($input) != $1_dim0) { - PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Size mismatch. Expected $1_dim0 elements"); + SWIG_fail; } for (i = 0; i < $1_dim0; i++) { - PyObject *o = PySequence_GetItem($input,i); + PyObject *o = PySequence_GetItem($input, i); if (PyNumber_Check(o)) { temp[i] = (float) PyFloat_AsDouble(o); } else { - PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Sequence elements must be numbers"); + SWIG_fail; } } $1 = temp; @@ -2997,7 +3068,7 @@ array dimensions. Multidimensional arrays can be matched in a similar manner.

     %typemap(in) float matrix[ANY][ANY] (float temp[$1_dim0][$1_dim1]) {
    -   ... convert a 2d array ...
    +  ... convert a 2d array ...
     }
     
    @@ -3012,27 +3083,27 @@ as shown. To work with heap allocated data, the following technique can be use %typemap(in) float value[ANY] { int i; if (!PySequence_Check($input)) { - PyErr_SetString(PyExc_ValueError,"Expected a sequence"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Expected a sequence"); + SWIG_fail; } if (PySequence_Length($input) != $1_dim0) { - PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Size mismatch. Expected $1_dim0 elements"); + SWIG_fail; } $1 = (float *) malloc($1_dim0*sizeof(float)); for (i = 0; i < $1_dim0; i++) { - PyObject *o = PySequence_GetItem($input,i); + PyObject *o = PySequence_GetItem($input, i); if (PyNumber_Check(o)) { $1[i] = (float) PyFloat_AsDouble(o); } else { - PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers"); free($1); - return NULL; + PyErr_SetString(PyExc_ValueError, "Sequence elements must be numbers"); + SWIG_fail; } } } %typemap(freearg) float value[ANY] { - if ($1) free($1); + if ($1) free($1); } @@ -3129,7 +3200,7 @@ To fix this, you can write an "out" typemap. For example: $result = PyList_New($1_dim0); for (i = 0; i < $1_dim0; i++) { PyObject *o = PyFloat_FromDouble((double) $1[i]); - PyList_SetItem($result,i,o); + PyList_SetItem($result, i, o); } } @@ -3153,7 +3224,7 @@ Now, you will find that member access is quite nice: useless and has since been eliminated. To return structure members, simply use the "out" typemap.

    -

    11.6.2 Implementing constraints with typemaps

    +

    13.6.2 Implementing constraints with typemaps

    @@ -3187,10 +3258,10 @@ pointers. For example:

     %typemap(check) Vector * {
    -    if ($1 == 0) {
    -        PyErr_SetString(PyExc_TypeError,"NULL Pointer not allowed");
    -        return NULL;
    -   }
    +  if ($1 == 0) {
    +    PyErr_SetString(PyExc_TypeError, "NULL Pointer not allowed");
    +    SWIG_fail;
    +  }
     }
     
     
    @@ -3201,7 +3272,7 @@ a NULL pointer. As a result, SWIG can often prevent a potential segmentation faults or other run-time problems by raising an exception rather than blindly passing values to the underlying C/C++ program.

    -

    11.7 Typemaps for multiple target languages

    +

    13.7 Typemaps for multiple target languages

    @@ -3228,15 +3299,15 @@ The example above also shows a common approach of issuing a warning for an as ye

    Compatibility note: In SWIG-1.1 different languages could be distinguished with the language name being put within the %typemap directive, for example,
    -%typemap(ruby,in) int "$1 = NUM2INT($input);". +%typemap(ruby, in) int "$1 = NUM2INT($input);".

    -

    11.8 Optimal code generation when returning by value

    +

    13.8 Optimal code generation when returning by value

    The "out" typemap is the main typemap for return types. -This typemap supports an optional attribute flag called "optimal", which is for reducing +This typemap supports an optional attribute flag called "optimal", which is for reducing the number of temporary variables and the amount of generated code, thereby giving the compiler the opportunity to use return value optimization for generating faster executing code. It only really makes a difference when returning objects by value and has some limitations on usage, @@ -3420,7 +3491,7 @@ example.i:7: Warning 475: optimal attribute usage in the out typemap. However, it doesn't always get it right, for example when $1 is within some commented out code.

    -

    11.9 Multi-argument typemaps

    +

    13.9 Multi-argument typemaps

    @@ -3468,16 +3539,16 @@ maps perform the conversion described for the above example: int i; if (!PyList_Check($input)) { PyErr_SetString(PyExc_ValueError, "Expecting a list"); - return NULL; + SWIG_fail; } $1 = PyList_Size($input); $2 = (char **) malloc(($1+1)*sizeof(char *)); for (i = 0; i < $1; i++) { - PyObject *s = PyList_GetItem($input,i); + PyObject *s = PyList_GetItem($input, i); if (!PyString_Check(s)) { - free($2); - PyErr_SetString(PyExc_ValueError, "List items must be strings"); - return NULL; + free($2); + PyErr_SetString(PyExc_ValueError, "List items must be strings"); + SWIG_fail; } $2[i] = PyString_AsString(s); } @@ -3485,7 +3556,7 @@ maps perform the conversion described for the above example: } %typemap(freearg) (int argc, char *argv[]) { - if ($2) free($2); + if ($2) free($2); } /* Required for C++ method overloading */ @@ -3591,38 +3662,38 @@ might write typemaps like this:

     // typemap for an outgoing buffer
     %typemap(in) (void *wbuffer, size_t len) {
    -   if (!PyString_Check($input)) {
    -       PyErr_SetString(PyExc_ValueError, "Expecting a string");
    -       return NULL;
    -   }
    -   $1 = (void *) PyString_AsString($input);
    -   $2 = PyString_Size($input);
    +  if (!PyString_Check($input)) {
    +    PyErr_SetString(PyExc_ValueError, "Expecting a string");
    +    SWIG_fail;
    +  }
    +  $1 = (void *) PyString_AsString($input);
    +  $2 = PyString_Size($input);
     }
     
     // typemap for an incoming buffer
     %typemap(in) (void *rbuffer, size_t len) {
    -   if (!PyInt_Check($input)) {
    -       PyErr_SetString(PyExc_ValueError, "Expecting an integer");
    -       return NULL;
    -   }
    -   $2 = PyInt_AsLong($input);
    -   if ($2 < 0) {
    -       PyErr_SetString(PyExc_ValueError, "Positive integer expected");
    -       return NULL;
    -   }
    -   $1 = (void *) malloc($2);
    +  if (!PyInt_Check($input)) {
    +    PyErr_SetString(PyExc_ValueError, "Expecting an integer");
    +    SWIG_fail;
    +  }
    +  $2 = PyInt_AsLong($input);
    +  if ($2 < 0) {
    +    PyErr_SetString(PyExc_ValueError, "Positive integer expected");
    +    SWIG_fail;
    +  }
    +  $1 = (void *) malloc($2);
     }
     
     // Return the buffer.  Discarding any previous return result
     %typemap(argout) (void *rbuffer, size_t len) {
    -   Py_XDECREF($result);   /* Blow away any previous result */
    -   if (result < 0) {      /* Check for I/O error */
    -       free($1);
    -       PyErr_SetFromErrno(PyExc_IOError);
    -       return NULL;
    -   }
    -   $result = PyString_FromStringAndSize($1,result);
    -   free($1);
    +  Py_XDECREF($result);   /* Blow away any previous result */
    +  if (result < 0) {      /* Check for I/O error */
    +    free($1);
    +    PyErr_SetFromErrno(PyExc_IOError);
    +    return NULL;
    +  }
    +  $result = PyString_FromStringAndSize($1, result);
    +  free($1);
     }
     
    @@ -3640,16 +3711,16 @@ Now, in a script, you can write code that simply passes buffers as strings like
     >>> f = example.open("Makefile")
    ->>> example.read(f,40)
    +>>> example.read(f, 40)
     'TOP        = ../..\nSWIG       = $(TOP)/.'
    ->>> example.read(f,40)
    +>>> example.read(f, 40)
     './swig\nSRCS       = example.c\nTARGET    '
     >>> example.close(f)
     0
     >>> g = example.open("foo", example.O_WRONLY | example.O_CREAT, 0644)
    ->>> example.write(g,"Hello world\n")
    +>>> example.write(g, "Hello world\n")
     12
    ->>> example.write(g,"This is a test\n")
    +>>> example.write(g, "This is a test\n")
     15
     >>> example.close(g)
     0
    @@ -3677,13 +3748,13 @@ this, you could write a multi-argument typemap like this:
     
     %typemap(in) (double *mat, int rows, int columns) {
    -    MatrixObject *a;
    -    a = GetMatrixFromObject($input);     /* Get matrix somehow */
    +  MatrixObject *a;
    +  a = GetMatrixFromObject($input);     /* Get matrix somehow */
     
    -    /* Get matrix properties */
    -    $1 = GetPointer(a);
    -    $2 = GetRows(a);
    -    $3 = GetColumns(a);
    +  /* Get matrix properties */
    +  $1 = GetPointer(a);
    +  $2 = GetRows(a);
    +  $3 = GetColumns(a);
     }
     
    @@ -3697,7 +3768,7 @@ with non-consecutive C/C++ arguments; a workaround such as a helper function re- the arguments to make them consecutive will need to be written.

    -

    11.10 Typemap warnings

    +

    13.10 Typemap warnings

    @@ -3706,7 +3777,7 @@ See the information in the issuing warnings

    -

    11.11 Typemap fragments

    +

    13.11 Typemap fragments

    @@ -3864,9 +3935,9 @@ A fragment can use one or more additional fragments, for example:

    -%fragment("<limits.h>", "header") {
    -  %#include <limits.h>
    -}
    +%fragment("<limits.h>", "header") %{
    +  #include <limits.h>
    +%}
     
     
     %fragment("AsMyClass", "header", fragment="<limits.h>") {
    @@ -3876,9 +3947,9 @@ A fragment can use one or more additional fragments, for example:
         ... some marshalling code  ...
     
         if  (ival < CHAR_MIN /*defined in <limits.h>*/) {
    -       ...
    +      ...
         } else {
    -       ...
    +      ...
         }
         ...
         return value;
    @@ -3919,7 +3990,7 @@ list. Consider:
     
     
    -%typemap(in, fragment="frag1,frag2,frag3") {...}
    +%typemap(in, fragment="frag1, frag2, frag3") {...}
     
    @@ -3949,8 +4020,91 @@ Finally, you can force the inclusion of a fragment at any point in the generated

    -which is very useful inside a template class, for example. +which, for example, is very useful inside a template class. +Another useful case is when using %extend inside a class +where the additional code in the %extend block depends on the contents of the fragment.

    + +
    +
    +%fragment("<limits.h>", "header") %{
    +  #include <limits.h>
    +%}
    +
    +struct X {
    +  ...
    +  %extend {
    +    %fragment("<limits.h>");
    +    bool check(short val) {
    +      if (val < SHRT_MIN /*defined in <limits.h>*/) {
    +        return true;
    +      } else {
    +        return false;
    +      }
    +    }
    +  }
    +};
    +
    +
    + + +

    +Forced inclusion of fragments can be used as a replacement for code insertion block, ensuring the +code block is only generated once. +Consider the contents of FileA.i below which first uses a code insertion block and then a forced fragment inclusion to generate code: +

    +
    +
    +// FileA.i
    +%{
    +  #include <stdio.h>
    +%}
    +%fragment("<limits.h>");
    +
    +
    + +

    +and another file including the above: +

    + +
    +
    +// FileB.i
    +%include "FileA.i"
    +
    +
    + +

    +The resulting code in the wrappers for FileB.i is: +

    + +
    +
    +  #include <stdio.h>
    +
    +  #include <limits.h>
    +
    +
    + +

    +A note of caution must be mentioned when using %fragment forced inclusion or code insertion blocks with %import. +If %import is used instead: +

    + +
    +
    +// FileC.i
    +%import "FileA.i"
    +
    +
    + +

    +then nothing is generated in the resulting code in the wrappers for FileC.i. +This is because %import is for collecting type information and does not result in any code +being generated, see File Imports. +

    + +

    @@ -3959,7 +4113,7 @@ fragment usage unless a desire to really get to grips with some powerful but tricky macro and fragment usage that is used in parts of the SWIG typemap library.

    -

    11.11.1 Fragment type specialization

    +

    13.11.1 Fragment type specialization

    @@ -3986,13 +4140,13 @@ struct A { } %typemap(in, fragment="incode"{A<T>}) { - ... here we use the 'type specialized' fragment "incode"{A<T>} ... + ... here we use the 'type specialized' fragment "incode"{A<T>} ... } };

    -

    11.11.2 Fragments and automatic typemap specialization

    +

    13.11.2 Fragments and automatic typemap specialization

    @@ -4038,7 +4192,7 @@ The interested (or very brave) reader can take a look at the fragments.swg file

    -

    11.12 The run-time type checker

    +

    13.12 The run-time type checker

    @@ -4064,7 +4218,7 @@ language modules.

  • Modules can be unloaded from the type system.
  • -

    11.12.1 Implementation

    +

    13.12.1 Implementation

    @@ -4099,15 +4253,18 @@ For example:

     class Foo {
    -   int x;
    +public:
    +  int x;
     };
     
     class Bar {
    -   int y;
    +public:
    +  int y;
     };
     
     class FooBar : public Foo, public Bar {
    -   int z;
    +public:
    +  int z;
     };
     
    @@ -4141,12 +4298,15 @@ handling of pointer values (and to make adjustments when needed).

    In the wrapper code generated for each language, pointers are handled through the use of special type descriptors and conversion functions. For example, -if you look at the wrapper code for Python, you will see code like this: +if you look at the wrapper code for Python, you will see code similar to the following +(simplified for brevity):

    -if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Foo,1)) == -1) return NULL;
    +if (!SWIG_IsOK(SWIG_ConvertPtr(obj0, (void **) &arg1, SWIGTYPE_p_Foo, 0))) {
    +  SWIG_exception_fail(SWIG_TypeError, "in method 'GrabVal', expecting type Foo");
    +}
     
    @@ -4158,8 +4318,10 @@ target language, a list of equivalent typenames (via typedef or inheritance), and pointer value handling information (if applicable). The SWIG_ConvertPtr() function is simply a utility function that takes a pointer object in the target language and a -type-descriptor objects and uses this information to generate a C++ -pointer. However, the exact name and calling conventions of the conversion +type-descriptor object and uses this information to generate a C++ pointer. +The SWIG_IsOK macro checks the return value for errors and +SWIG_exception_fail can be called to raise an exception in the target language. +However, the exact name and calling conventions of the conversion function depends on the target language (see language specific chapters for details).

    @@ -4250,7 +4412,7 @@ structures rather than creating new ones. These swig_module_info structures are chained together in a circularly linked list.

    -

    11.12.2 Usage

    +

    13.12.2 Usage

    This section covers how to use these functions from typemaps. To learn how to @@ -4265,7 +4427,9 @@ similar to this:

     %typemap(in) Foo * {
    -  if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor)) == -1) return NULL;
    +  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
    +    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
    +  }
     }
     
    @@ -4298,12 +4462,12 @@ descriptor name for any C datatype. For example:
     %typemap(in) Foo * {
    -  if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor)) == -1) {
    -     Bar *temp;
    -     if ((SWIG_ConvertPtr($input, (void **) &temp, $descriptor(Bar *)) == -1) {
    -         return NULL;
    -     }
    -     $1 = (Foo *) temp;
    +  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
    +    Bar *temp;
    +    if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &temp, $descriptor(Bar *), 0))) {
    +      SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo or Bar");
    +    }
    +    $1 = (Foo *)temp;
       }
     }
     
    @@ -4344,7 +4508,7 @@ probably just look at the output of SWIG to get a better sense for how types are managed.

    -

    11.13 Typemaps and overloading

    +

    13.13 Typemaps and overloading

    @@ -4371,7 +4535,7 @@ You can access the functions in a normal way from the scripting interpreter: # Python foo(3) # foo(int) foo(3.5) # foo(double) -foo("hello",5) # foo(char *, int) +foo("hello", 5) # foo(char *, int) # Tcl foo 3 # foo(int) @@ -4389,32 +4553,32 @@ For example, the above functions would produce something roughly like this:

     // wrapper pseudocode
     _wrap_foo_0(argc, args[]) {       // foo(int)
    -   int arg1;
    -   int result;
    -   ...
    -   arg1 = FromInteger(args[0]);
    -   result = foo(arg1);
    -   return ToInteger(result);
    +  int arg1;
    +  int result;
    +  ...
    +  arg1 = FromInteger(args[0]);
    +  result = foo(arg1);
    +  return ToInteger(result);
     }
     
     _wrap_foo_1(argc, args[]) {       // foo(double)
    -   double arg1;
    -   int result;
    -   ...
    -   arg1 = FromDouble(args[0]);
    -   result = foo(arg1);
    -   return ToInteger(result);
    +  double arg1;
    +  int result;
    +  ...
    +  arg1 = FromDouble(args[0]);
    +  result = foo(arg1);
    +  return ToInteger(result);
     }
     
     _wrap_foo_2(argc, args[]) {       // foo(char *, int)
    -   char *arg1;
    -   int   arg2;
    -   int result;
    -   ...
    -   arg1 = FromString(args[0]);
    -   arg2 = FromInteger(args[1]);
    -   result = foo(arg1,arg2);
    -   return ToInteger(result);
    +  char *arg1;
    +  int   arg2;
    +  int result;
    +  ...
    +  arg1 = FromString(args[0]);
    +  arg2 = FromInteger(args[1]);
    +  result = foo(arg1, arg2);
    +  return ToInteger(result);
     }
     
     
    @@ -4427,20 +4591,20 @@ Next, a dynamic dispatch function is generated:
     _wrap_foo(argc, args[]) {
    -   if (argc == 1) {
    -       if (IsInteger(args[0])) {
    -           return _wrap_foo_0(argc,args);
    -       } 
    -       if (IsDouble(args[0])) {
    -           return _wrap_foo_1(argc,args);
    -       }
    -   }
    -   if (argc == 2) {
    -       if (IsString(args[0]) && IsInteger(args[1])) {
    -          return _wrap_foo_2(argc,args);
    -       }
    -   }
    -   error("No matching function!\n");
    +  if (argc == 1) {
    +    if (IsInteger(args[0])) {
    +      return _wrap_foo_0(argc, args);
    +    }
    +    if (IsDouble(args[0])) {
    +      return _wrap_foo_1(argc, args);
    +    }
    +  }
    +  if (argc == 2) {
    +    if (IsString(args[0]) && IsInteger(args[1])) {
    +      return _wrap_foo_2(argc, args);
    +    }
    +  }
    +  error("No matching function!\n");
     }
     
    @@ -4518,7 +4682,7 @@ The following excerpt from the Python module illustrates this:
     /* Python type checking rules */
    -/* Note:  %typecheck(X) is a macro for %typemap(typecheck,precedence=X) */
    +/* Note:  %typecheck(X) is a macro for %typemap(typecheck, precedence=X) */
     
     %typecheck(SWIG_TYPECHECK_INTEGER)
       int, short, long,
    @@ -4549,38 +4713,13 @@ The following excerpt from the Python module illustrates this:
       $1 = PyString_Check($input) ? 1 : 0;
     }
     
    -%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] {
    -  void *ptr;
    -  if (SWIG_ConvertPtr($input, (void **) &ptr, $1_descriptor, 0) == -1) {
    -    $1 = 0;
    -    PyErr_Clear();
    -  } else {
    -    $1 = 1;
    -  }
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, noblock=1) SWIGTYPE * {
    +  void *vptr = 0;
    +  int res = SWIG_ConvertPtr($input, &vptr, $1_descriptor, 0);
    +  $1 = SWIG_IsOK(res) ? 1 : 0;
     }
     
    -%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE {
    -  void *ptr;
    -  if (SWIG_ConvertPtr($input, (void **) &ptr, $&1_descriptor, 0) == -1) {
    -    $1 = 0;
    -    PyErr_Clear();
    -  } else {
    -    $1 = 1;
    -  }
    -}
    -
    -%typecheck(SWIG_TYPECHECK_VOIDPTR) void * {
    -  void *ptr;
    -  if (SWIG_ConvertPtr($input, (void **) &ptr, 0, 0) == -1) {
    -    $1 = 0;
    -    PyErr_Clear();
    -  } else {
    -    $1 = 1;
    -  }
    -}
    -
    -%typecheck(SWIG_TYPECHECK_POINTER) PyObject *
    -{
    +%typecheck(SWIG_TYPECHECK_POINTER) PyObject * {
       $1 = ($input != 0);
     }
     
    @@ -4612,11 +4751,11 @@ Here is an example,
     // Typemap for a C++ string
     %typemap(in) std::string {
    -    if (PyString_Check($input)) {
    -         $1 = std::string(PyString_AsString($input));
    -     } else {
    -         SWIG_exception(SWIG_TypeError, "string expected");
    -     }
    +  if (PyString_Check($input)) {
    +    $1 = std::string(PyString_AsString($input));
    +  } else {
    +    SWIG_exception(SWIG_TypeError, "string expected");
    +  }
     }
     // Copy the typecheck code for "char *".  
     %typemap(typecheck) std::string = char *;
    @@ -4634,8 +4773,8 @@ If you write a typecheck typemap and omit the precedence level, for example comm
     
     
    -%typemap(typecheck /*,precedence=SWIG_TYPECHECK_INTEGER*/) int {
    -   $1 = PyInt_Check($input) ? 1 : 0;
    +%typemap(typecheck /*, precedence=SWIG_TYPECHECK_INTEGER*/) int {
    +  $1 = PyInt_Check($input) ? 1 : 0;
     }
     
    @@ -4646,7 +4785,8 @@ then the type is given a precedence higher than any other known precedence level
    -example.i:18: Warning 467: Overloaded method foo(int) not supported (incomplete type checking rule - no precedence level in typecheck typemap for 'int').
    +example.i:18: Warning 467: Overloaded method foo(int) not supported (incomplete type
    +checking rule - no precedence level in typecheck typemap for 'int').
     
    @@ -4671,33 +4811,135 @@ simply check the type of the first array element and use that to dispatch to the Subsequent "in" typemaps would then perform more extensive type-checking. -
  • Make sure you read the section on overloading in the "SWIG and C++" chapter. +
  • Make sure you read the section on overloading in the SWIG and C++ chapter.
  • -

    11.14 More about %apply and %clear

    +

    13.13.1 SWIG_TYPECHECK_POINTER precedence level and the typecheck typemap

    -In order to implement certain kinds of program behavior, it is sometimes necessary to -write sets of typemaps. For example, to support output arguments, one often writes -a set of typemaps like this: +When it comes to overloading of a particular type passed by value, pointer or reference (const and non-const), +a C++ compiler can disambiguate which overloaded function to call. +However, SWIG effectively treats these as pointers in the target language and thus as equivalent types. +For example, consider:

    -%typemap(in,numinputs=0) int *OUTPUT (int temp) {
    -   $1 = &temp;
    +class X { ... };
    +void m(X const &c); // equivalent: void m(X *c);
    +void m(X &r);       // equivalent: void m(X *r);
    +void m(X *p);       // equivalent: void m(X *p);
    +
    +
    + +

    +These cannot be disambiguated in the target languages and so SWIG will choose the first method and ignore the subsequent two methods. +The scripting languages do this by using the overload dispatch mechanism described earlier and warnings indicate this: +

    + +
    +
    +example.i:6: Warning 509: Overloaded method m(X &) effectively ignored,
    +example.i:5: Warning 509: as it is shadowed by m(X const &).
    +example.i:7: Warning 509: Overloaded method m(X *) effectively ignored,
    +example.i:5: Warning 509: as it is shadowed by m(X const &).
    +
    +
    + +

    +The statically typed languages like Java and C# automatically ignore all but the first equivalent overloaded methods with warnings: +

    + +
    +
    +example.i:6: Warning 516: Overloaded method m(X &) ignored,
    +example.i:5: Warning 516: using m(X const &) instead.
    +example.i:7: Warning 516: Overloaded method m(X *) ignored,
    +example.i:5: Warning 516: using m(X const &) instead.
    +
    +
    + +

    +You can select the overloaded method you would like to wrap by ignoring the other two with %ignore or rename two of them with %rename +and this will of course remove the warnings too. +The problem of ambiguity is also discussed in the C++ chapter on overloading. +

    + +

    +So how does this work with respect to typemaps? +The typemaps SWIG provides to handle overloading for these three methods are from the SWIGTYPE family. +As discussed earlier, in Default typemap matching rules, +the SWIGTYPE & typemaps are used for references and SWIGTYPE * typemaps are used for pointers. +SWIG uses the special SWIG_TYPECHECK_POINTER (0) precedence level to handle these types in the "typecheck" typemap: +

    + +
    +
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) SWIGTYPE & "..."
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) SWIGTYPE * "..."
    +
    +
    + +

    +When the SWIGTYPE "typecheck" typemaps use the SWIG_TYPECHECK_POINTER precedence level, +SWIG converts the type to a pointer equivalent type and then uses the equivalent type to detect if it can be disambiguated in an overloaded method in the target language. +In our example above, the equivalent types for X const &, X & and X * are all X *. +As they are the same, they cannot be disambiguated and so just the first overloaded method is chosen. +

    + +

    +The automatic conversion to equivalent types and subsequent type comparison is triggered via the use of the special SWIG_TYPECHECK_POINTER precedence level +and works for types passed by value, pointer and reference. +Alas, there are more ways to overload a method that also need handling. +C++ smart pointers are such a type which can be disambiguated by a C++ compiler but not automatically by SWIG. +SWIG does not automatically know that a smart pointer has an equivalent type, but it can be told manually. +Just specify the 'equivalent' attribute in the "typecheck" typemap with a pointer to the underlying type. +

    + +
    +
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="X *") MySmartPtr<X> " ... "
    +
    +void m(X &r);            // equivalent: void m(X *r);
    +void m(MySmartPtr<X> s); // equivalent: void m(X *s);
    +
    +
    + +

    +Now SWIG will detect the two types are equivalent and generate valid code by wrapping just the first overloaded method. +You can of course choose which method to wrap by ignoring one of them with %ignore. +Otherwise both can be wrapped by removing the overloading name ambiguity by renaming one of them with %rename. +

    + +

    +The 'equivalent' attribute is used in the implementation for the shared_ptr smart pointer library. +

    + +

    13.14 More about %apply and %clear

    + + +

    +In order to implement certain kinds of program behavior, it is sometimes necessary to +write a family of typemap methods. For example, to support output arguments, one often writes +a family of typemaps like this: +

    + +
    +
    +%typemap(in, numinputs=0) int *OUTPUT (int temp) {
    +  $1 = &temp;
     }
     %typemap(argout) int *OUTPUT {
    -   // return value somehow
    +  // return value somehow
     }
     

    To make it easier to apply the typemap to different argument types and names, the %apply directive -performs a copy of all typemaps from one type to another. For example, if you specify this, +performs a copy of all typemaps from a source type to one or more set of target types. For example, if you specify this,

    @@ -4707,12 +4949,14 @@ performs a copy of all typemaps from one type to another. For example, if you s

    -then all of the int *OUTPUT typemaps are copied to int *retvalue and int32 *output. +then all of the int *OUTPUT (source) typemap methods are copied to int *retvalue and int32 *output (the targets).

    -However, there is a subtle aspect of %apply that needs more description. Namely, %apply does not -overwrite a typemap rule if it is already defined for the target datatype. This behavior allows you to do two things: +However, there is a subtle aspect of %apply that needs clarification. +Namely, if a target contains a typemap method that the source does not, +the target typemap method remains in place and unchanged. +This behavior allows you to do two things:

      @@ -4720,7 +4964,7 @@ overwrite a typemap rule if it is already defined for the target datatype. Thi %apply to incorporate the remaining pieces. -
    • Sets of different typemaps can be applied to the same datatype using repeated %apply directives. +
    • Different typemaps can be applied to the same datatype using repeated %apply directives.
    @@ -4731,17 +4975,21 @@ For example:
     %typemap(in) int *INPUT (int temp) {
    -   temp = ... get value from $input ...;
    -   $1 = &temp;
    +  temp = ... get value from $input ...;
    +  $1 = &temp;
     }
     
     %typemap(check) int *POSITIVE {
    -   if (*$1 <= 0) {
    -      SWIG_exception(SWIG_ValueError,"Expected a positive number!\n");
    -      return NULL;
    -   }
    +  if (*$1 <= 0) {
    +    SWIG_exception(SWIG_ValueError, "Expected a positive number!\n");
    +    return NULL;
    +  }
     }
     
    +%typemap(arginit) int *invalue %{
    +  $1 = NULL;
    +%}
    +
     ...
     %apply int *INPUT     { int *invalue };
     %apply int *POSITIVE  { int *invalue };
    @@ -4749,9 +4997,11 @@ For example:
     

    -Since %apply does not overwrite or replace any existing rules, the only way to reset behavior is to -use the %clear directive. %clear removes all typemap rules defined for a specific datatype. For -example: +In this example, neither of the two %apply directives will overwrite / delete the "arginit" typemap as neither has an "arginit" typemap. +The result is a family of three relevant typemaps for int *invalue. +Since %apply does not overwrite / delete any existing rules, the only way to reset behavior is to +delete them, such as with the %clear directive. +For example:

    @@ -4760,8 +5010,19 @@ example:
    +

    +will delete the typemaps for all the typemap methods; namely "in", "check" and "arginit". Alternatively delete each one individually: +

    -

    11.15 Passing data between typemaps

    +
    +
    +%typemap(in) int *invalue;
    +%typemap(check) int *invalue;
    +%typemap(arginit) int *invalue;
    +
    +
    + +

    13.15 Passing data between typemaps

    @@ -4777,13 +5038,13 @@ to them. For example, you could do this:

     %typemap(in) int *(int temp) {
    -   temp = (int) PyInt_AsLong($input);
    -   $1 = &temp;
    +  temp = (int) PyInt_AsLong($input);
    +  $1 = &temp;
     }
     
     %typemap(argout) int * {
    -   PyObject *o = PyInt_FromLong(temp$argnum);
    -   ...
    +  PyObject *o = PyInt_FromLong(temp$argnum);
    +  ...
     }
     
    @@ -4798,7 +5059,7 @@ sure that the typemaps sharing information have exactly the same types and names

    -

    11.16 C++ "this" pointer

    +

    13.16 C++ "this" pointer

    @@ -4858,7 +5119,7 @@ will also match the typemap. One work around is to create an interface file tha the method, but gives the argument a name other than self.

    -

    11.17 Where to go for more information?

    +

    13.17 Where to go for more information?

    diff --git a/Doc/Manual/Varargs.html b/Doc/Manual/Varargs.html index 1c99804f1..9f20469d2 100644 --- a/Doc/Manual/Varargs.html +++ b/Doc/Manual/Varargs.html @@ -7,7 +7,7 @@ -

    14 Variable Length Arguments

    +

    16 Variable Length Arguments

      @@ -43,7 +43,7 @@ added in SWIG-1.3.12. Most other wrapper generation tools have wisely chosen to avoid this issue.

      -

      14.1 Introduction

      +

      16.1 Introduction

      @@ -95,7 +95,7 @@ int execlp(const char *path, const char *arg1, ...); ... /* Example */ -execlp("ls","ls","-l",NULL); +execlp("ls", "ls", "-l", NULL);

    @@ -126,21 +126,21 @@ example:
     List make_list(const char *s, ...) {
    -    va_list ap;
    -    List    x;
    -    ...
    -    va_start(ap, s);
    -    while (s) {
    -       x.append(s);
    -       s = va_arg(ap, const char *);
    -    }
    -    va_end(ap);
    -    return x;
    +  va_list ap;
    +  List    x;
    +  ...
    +  va_start(ap, s);
    +  while (s) {
    +    x.append(s);
    +    s = va_arg(ap, const char *);
    +  }
    +  va_end(ap);
    +  return x;
     }
     
    -

    14.2 The Problem

    +

    16.2 The Problem

    @@ -188,12 +188,12 @@ In contrast, suppose you attempted to make some kind of wrapper around

     int wrap_printf(const char *fmt, ...) {
    -   va_list ap;
    -   va_start(ap,fmt);
    -   ...
    -   printf(fmt,ap);
    -   ...
    -   va_end(ap);
    +  va_list ap;
    +  va_start(ap, fmt);
    +  ...
    +  printf(fmt, ap);
    +  ...
    +  va_end(ap);
     };
     
    @@ -233,7 +233,7 @@ can also support real varargs wrapping (with stack-frame manipulation) if you are willing to get hands dirty. Keep reading.

    -

    14.3 Default varargs support

    +

    16.3 Default varargs support

    @@ -302,7 +302,7 @@ Read on for further solutions.

    -

    14.4 Argument replacement using %varargs

    +

    16.4 Argument replacement using %varargs

    @@ -413,7 +413,7 @@ mixed argument types such as printf(). Providing general purpose wrappers to such functions presents special problems (covered shortly).

    -

    14.5 Varargs and typemaps

    +

    16.5 Varargs and typemaps

    @@ -423,8 +423,8 @@ Variable length arguments may be used in typemap specifications. For example:

     %typemap(in) (...) {
    -    // Get variable length arguments (somehow)
    -    ...
    +  // Get variable length arguments (somehow)
    +  ...
     }
     
     %typemap(in) (const char *fmt, ...) {
    @@ -471,15 +471,15 @@ like this:
     
     wrap_printf() {
    -   char *arg1;
    -   void *arg2;
    -   int   result;
    +  char *arg1;
    +  void *arg2;
    +  int   result;
     
    -   arg1 = "%s";
    -   arg2 = (void *) PyString_AsString(arg2obj);
    -   ...
    -   result = printf(arg1,arg2);
    -   ...
    +  arg1 = "%s";
    +  arg2 = (void *) PyString_AsString(arg2obj);
    +  ...
    +  result = printf(arg1, arg2);
    +  ...
     }
     
    @@ -517,7 +517,7 @@ like this: argc = PyTuple_Size(varargs); if (argc > 10) { PyErr_SetString(PyExc_ValueError, "Too many arguments"); - return NULL; + SWIG_fail; } for (i = 0; i < argc; i++) { PyObject *pyobj = PyTuple_GetItem(varargs, i); @@ -525,16 +525,19 @@ like this: %#if PY_VERSION_HEX>=0x03000000 PyObject *pystr; if (!PyUnicode_Check(pyobj)) { - PyErr_SetString(PyExc_ValueError, "Expected a string"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Expected a string"); + SWIG_fail; } pystr = PyUnicode_AsUTF8String(pyobj); + if (!pystr) { + SWIG_fail; + } str = strdup(PyBytes_AsString(pystr)); - Py_XDECREF(pystr); + Py_DECREF(pystr); %#else if (!PyString_Check(pyobj)) { - PyErr_SetString(PyExc_ValueError, "Expected a string"); - return NULL; + PyErr_SetString(PyExc_ValueError, "Expected a string"); + SWIG_fail; } str = PyString_AsString(pyobj); %#endif @@ -590,7 +593,7 @@ really want to elevate your guru status and increase your job security, continue to the next section.

    -

    14.6 Varargs wrapping with libffi

    +

    16.6 Varargs wrapping with libffi

    @@ -626,23 +629,23 @@ example. For example: of strings */ %typemap(in) (...) { - char **argv; - int argc; - int i; + char **argv; + int argc; + int i; - argc = PyTuple_Size(varargs); - argv = (char **) malloc(sizeof(char *)*(argc+1)); - for (i = 0; i < argc; i++) { - PyObject *o = PyTuple_GetItem(varargs,i); - if (!PyString_Check(o)) { - PyErr_SetString(PyExc_ValueError,"Expected a string"); - free(argv); - return NULL; - } - argv[i] = PyString_AsString(o); - } - argv[i] = NULL; - $1 = (void *) argv; + argc = PyTuple_Size(varargs); + argv = (char **) malloc(sizeof(char *)*(argc+1)); + for (i = 0; i < argc; i++) { + PyObject *o = PyTuple_GetItem(varargs, i); + if (!PyString_Check(o)) { + free(argv); + PyErr_SetString(PyExc_ValueError, "Expected a string"); + SWIG_fail; + } + argv[i] = PyString_AsString(o); + } + argv[i] = NULL; + $1 = (void *) argv; } /* Rewrite the function call, using libffi */ @@ -676,11 +679,11 @@ example. For example: &ffi_type_uint, types) == FFI_OK) { ffi_call(&cif, (void (*)()) execlp, &result, values); } else { - PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!"); free(types); free(values); free(arg3); - return NULL; + PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!"); + SWIG_fail; } free(types); free(values); @@ -733,7 +736,7 @@ As a more extreme example of libffi, here is some code that attempts to wrap -

    14.7 Wrapping of va_list

    +

    16.7 Wrapping of va_list

    @@ -896,7 +899,7 @@ int my_vprintf(const char *fmt, ...) {

    -

    14.8 C++ Issues

    +

    16.8 C++ Issues

    @@ -912,12 +915,12 @@ and it fully supports classes much like the %rename directive. For exa class Foo { public: - virtual void bar(char *arg, ...); // gets varargs above + virtual void bar(char *arg, ...); // gets varargs above }; class Spam: public Foo { public: - virtual void bar(char *arg, ...); // gets varargs above + virtual void bar(char *arg, ...); // gets varargs above };

    @@ -952,9 +955,9 @@ are placed in arg2, arg3, and so forth. For example:
     %feature("action") Foo::bar {
    -   ...
    -   result = arg1->bar(arg2, arg3, etc.);
    -   ...
    +  ...
    +  result = arg1->bar(arg2, arg3, etc.);
    +  ...
     }
     
    @@ -965,7 +968,7 @@ design or to provide an alternative interface using a helper function than it is fully general wrapper to a varargs C++ member function.

    -

    14.9 Discussion

    +

    16.9 Discussion

    @@ -987,10 +990,10 @@ you might structure your interface like this:

     %typemap(const char *fmt, ...) {
    -   ...
    +  ...
     }
     %feature("action") traceprintf {
    -   ...
    +  ...
     }
     
     /* Include some header file with traceprintf in it */
    @@ -1011,7 +1014,7 @@ to control this:
     
     #ifdef USE_LIBFFI
     %feature("action") printf {
    -   ...
    +  ...
     }
     #endif
     #ifdef USE_OTHERFFI
    diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html
    index 89a8375a5..c63d7de0c 100644
    --- a/Doc/Manual/Warnings.html
    +++ b/Doc/Manual/Warnings.html
    @@ -7,7 +7,7 @@
     
     
     
    -

    15 Warning Messages

    +

    18 Warning Messages

    @@ -36,7 +37,7 @@ -

    15.1 Introduction

    +

    18.1 Introduction

    @@ -56,7 +57,7 @@ where the generated wrapper code will probably compile, but it may not work like you expect.

    -

    15.2 Warning message suppression

    +

    18.2 Warning message suppression

    @@ -112,16 +113,16 @@ suppress a warning for a method in a class hierarchy, you could do this: %warnfilter(501) Object::foo; class Object { public: - int foo(int); - int foo(double); // Silently ignored - ... + int foo(int); + int foo(double); // Silently ignored + ... }; class Derived : public Object { public: - int foo(int); - int foo(double); // Silently ignored - ... + int foo(int); + int foo(double); // Silently ignored + ... };

    @@ -136,7 +137,7 @@ Warnings can be suppressed for an entire class by supplying a class name. For e class Object { public: - ... // All 501 warnings ignored in class + ... // All 501 warnings ignored in class }; @@ -148,7 +149,7 @@ your interface. Ignore the warning messages at your own peril.

    -

    15.3 Enabling extra warnings

    +

    18.3 Enabling extra warnings

    @@ -221,7 +222,7 @@ that is, any warnings suppressed or added in %warnfilter, #pragma S or the -w option.

    -

    15.4 Issuing a warning message

    +

    18.4 Issuing a warning message

    @@ -259,7 +260,7 @@ Warning messages can be associated with typemaps using the

     %typemap(in, warning="901:You are really going to regret this usage of $1_type $1_name") blah * {
    -   ...
    +  ...
     }
     
    @@ -275,7 +276,7 @@ example.i:24: Warning 901: You are really going to regret this usage of blah * s -

    15.5 Symbolic symbols

    +

    18.5 Symbolic symbols

    @@ -310,7 +311,7 @@ or -

    15.6 Commentary

    +

    18.6 Commentary

    @@ -327,7 +328,7 @@ no obvious recovery. There is no mechanism for suppressing error messages.

    -

    15.7 Warnings as errors

    +

    18.7 Warnings as errors

    @@ -336,7 +337,7 @@ option. This will cause SWIG to exit with a non successful exit code if a warning is encountered.

    -

    15.8 Message output format

    +

    18.8 Message output format

    @@ -355,10 +356,10 @@ $ swig -python -Fmicrosoft example.i example.i(4) : Syntax error in input(1). -

    15.9 Warning number reference

    +

    18.9 Warning number reference

    -

    15.9.1 Deprecated features (100-199)

    +

    18.9.1 Deprecated features (100-199)

      @@ -386,7 +387,7 @@ example.i(4) : Syntax error in input(1).
    • 126. The 'nestedworkaround' feature is deprecated.
    -

    15.9.2 Preprocessor (200-299)

    +

    18.9.2 Preprocessor (200-299)

      @@ -398,7 +399,7 @@ example.i(4) : Syntax error in input(1).
    • 206. Unexpected tokens after #directive directive.
    -

    15.9.3 C/C++ Parser (300-399)

    +

    18.9.3 C/C++ Parser (300-399)

      @@ -475,7 +476,7 @@ example.i(4) : Syntax error in input(1).
    • 395. operator delete[] ignored.
    -

    15.9.4 Types and typemaps (400-499)

    +

    18.9.4 Types and typemaps (400-499)

      @@ -506,7 +507,7 @@ example.i(4) : Syntax error in input(1). -

      15.9.5 Code generation (500-599)

      +

      18.9.5 Code generation (500-559)

        @@ -533,9 +534,22 @@ example.i(4) : Syntax error in input(1).
      • 521. Illegal destructor name name. Ignored.
      • 522. Use of an illegal constructor name 'name' in %extend is deprecated, the constructor name should be 'name'.
      • 523. Use of an illegal destructor name 'name' in %extend is deprecated, the destructor name should be 'name'. +
      • 524. Experimental target language. Target language language specified by lang is an experimental language. Please read about SWIG experimental languages, htmllink. +
      • 525. Destructor declaration is final, name cannot be a director class.
      -

      15.9.6 Language module specific (700-899)

      +

      18.9.6 Doxygen comments (560-599)

      + + +
        +
      • 560: Unknown Doxygen command: command.
      • +
      • 561: Unexpected end of Doxygen comment encountered.
      • +
      • 562: Expected Doxygen command: command
      • +
      • 563: Doxygen HTML error for tag tag: error text.
      • +
      • 564: Error parsing Doxygen command command: error text. Command ignored."
      • +
      + +

      18.9.7 Language module specific (700-899)

        @@ -586,14 +600,14 @@ example.i(4) : Syntax error in input(1).
      • 871. Unrecognized pragma pragma. (Php).
      -

      15.9.7 User defined (900-999)

      +

      18.9.8 User defined (900-999)

      These numbers can be used by your own application.

      -

      15.10 History

      +

      18.10 History

      diff --git a/Doc/Manual/Windows.html b/Doc/Manual/Windows.html index b95105bdd..800e2e420 100644 --- a/Doc/Manual/Windows.html +++ b/Doc/Manual/Windows.html @@ -68,7 +68,7 @@ SWIG does not come with the usual Windows type installation program, however it

      -The swigwin distribution contains the SWIG Windows executable, swig.exe, which will run on 32 bit versions of Windows, ie Windows 95 and later. +The swigwin distribution contains the SWIG Windows 32-bit executable, swig.exe, which will run on both 32-bit and 64-bit versions of Windows. If you want to build your own swig.exe have a look at Building swig.exe on Windows.

      @@ -149,7 +149,7 @@ PERL5_LIB: D:\nsPerl5.004_04\lib\CORE\perl.lib

      PYTHON_INCLUDE : Set this to the directory that contains Python.h
      -PYTHON_LIB : Set this to the python library including path for linking

      +PYTHON_LIB : Set this to the Python library including path for linking

      Example using Python 2.1.1:
      PYTHON_INCLUDE: D:\python21\include
      @@ -211,7 +211,7 @@ If you do not have access to Visual C++ you will have to set up project files /

      -SWIG can also be compiled and run using Cygwin or MinGW which provides a Unix like front end to Windows and comes free with gcc, an ANSI C/C++ compiler. However, this is not a recommended approach as the prebuilt executable is supplied. +SWIG can also be compiled and run using Cygwin or MinGW which provides a Unix like front end to Windows and comes free with gcc, an ISO C/C++ compiler. However, this is not a recommended approach as the prebuilt executable is supplied.

      3.3.1 Building swig.exe on Windows

      @@ -249,7 +249,7 @@ Execute the steps in the order shown and don't use spaces in path names. In fact
      1. Download the following packages from the MinGW download page - or MinGW SourceForge download page. + or MinGW SourceForge download page. Note that at the time of writing, the majority of these are in the Current release list and some are in the Snapshot or Previous release list.
          diff --git a/Doc/Manual/chapters b/Doc/Manual/chapters index f7b7d00c0..e38a9cd5f 100644 --- a/Doc/Manual/chapters +++ b/Doc/Manual/chapters @@ -5,6 +5,8 @@ Scripting.html SWIG.html SWIGPlus.html CPlusPlus11.html +CPlusPlus14.html +CPlusPlus17.html Preprocessor.html Library.html Arguments.html @@ -12,31 +14,27 @@ Typemaps.html Customization.html Contract.html Varargs.html +Doxygen.html Warnings.html Modules.html CCache.html -Allegrocl.html Android.html C.html CSharp.html -Chicken.html D.html Go.html Guile.html Java.html Javascript.html -Lisp.html Lua.html -Modula3.html -Mzscheme.html -Ocaml.html Octave.html Perl5.html Php.html -Pike.html Python.html R.html Ruby.html Scilab.html Tcl.html +Mzscheme.html +Ocaml.html Extending.html diff --git a/Doc/Manual/index.html b/Doc/Manual/index.html index 26cc81ea1..e720e70d0 100644 --- a/Doc/Manual/index.html +++ b/Doc/Manual/index.html @@ -1,11 +1,11 @@ -SWIG-3.0 Documentation +SWIG-4.0 Documentation -

          SWIG-3.0 Documentation

          +

          SWIG-4.0 Documentation

          The SWIG documentation is available in one of the following formats.
            diff --git a/Doc/Manual/makechap.py b/Doc/Manual/makechap.py index 61994e2a0..e30d14e0f 100644 --- a/Doc/Manual/makechap.py +++ b/Doc/Manual/makechap.py @@ -44,6 +44,8 @@ def getheadingname(m): def getheadingtext(m, s): prevheadingtext_newstyle = m.group(2) prevheadingtext_oldstyle = m.group(3) + if prevheadingtext_oldstyle is None or prevheadingtext_newstyle is None: + raise RuntimeError("Ill-formed heading in line:\n%s" % s) if len(prevheadingtext_oldstyle) == 0 and len(prevheadingtext_newstyle) == 0: raise RuntimeError("No heading text in line:\n%s" % s) if len(prevheadingtext_oldstyle) > 0 and len(prevheadingtext_newstyle) > 0: @@ -72,7 +74,7 @@ name = "" # Regexs for

            ,...

            sections -h1 = re.compile(r".*?

            (\s*[\d\s]*(.*?))*[\d\s]*(.*?)

            ", re.IGNORECASE) +h1 = re.compile(r".*?

            (\s*[\d\.\s]*(.*?))*[\d\.\s]*(.*?)

            ", re.IGNORECASE) h2 = re.compile(r".*?

            (\s*[\d\.\s]*(.*?))*[\d\.\s]*(.*?)

            ", re.IGNORECASE) h3 = re.compile(r".*?

            (\s*[\d\.\s]*(.*?))*[\d\.\s]*(.*?)

            ", re.IGNORECASE) h4 = re.compile(r".*?

            (\s*[\d\.\s]*(.*?))*[\d\.\s]*(.*?)

            ", re.IGNORECASE) diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 3e0d31c41..a66a58e2c 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -282,7 +282,7 @@ perl5_static_cpp: $(SRCDIR_SRCS) # ----------------------------------------------------------------- perl5_run: - $(RUNTOOL) $(PERL) $(PERL5_SCRIPT) $(RUNPIPE) + $(RUNTOOL) $(PERL) -I. $(PERL5_SCRIPT) $(RUNPIPE) # ----------------------------------------------------------------- # Version display @@ -334,8 +334,8 @@ else SWIGOPTPY3 = -py3 endif -PEP8 = @PEP8@ -PEP8_FLAGS = --ignore=E402,E501,E30,W291,W391 +PYCODESTYLE = @PYCODESTYLE@ +PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,W291,W391 # ---------------------------------------------------------------- # Build a C dynamically loadable module @@ -386,11 +386,11 @@ else PYSCRIPT = $(RUNME)3.py endif -PY2TO3 = 2to3 `2to3 -l | grep -v -E "Available|import$$" | awk '{print "-f "$$0}'` +PY2TO3 = @PY2TO3@ `@PY2TO3@ -l | grep -v -E "Available|import$$" | awk '{print "-f "$$0}'` python_run: $(PYSCRIPT) -ifneq (,$(PEP8)) - $(COMPILETOOL) $(PEP8) $(PEP8_FLAGS) $(PYSCRIPT) +ifneq (,$(PYCODESTYLE)) + $(COMPILETOOL) $(PYCODESTYLE) $(PYCODESTYLE_FLAGS) $(PYSCRIPT) endif env PYTHONPATH=$$PWD $(RUNTOOL) $(PYTHON) $(PYSCRIPT) $(RUNPIPE) @@ -463,7 +463,7 @@ octave_cpp: $(SRCDIR_SRCS) # ----------------------------------------------------------------- octave_run: - OCTAVE_HISTFILE=/dev/null $(RUNTOOL) $(OCTAVE) $(OCTAVE_SCRIPT) $(RUNPIPE) + env OCTAVE_PATH= OCTAVE_HISTFILE=/dev/null $(RUNTOOL) $(OCTAVE) $(OCTAVE_SCRIPT) $(RUNPIPE) # ----------------------------------------------------------------- # Version display @@ -671,7 +671,7 @@ javascript_build: $(SRCDIR_SRCS) javascript_build_cpp: $(SRCDIR_SRCS) ifeq (node,$(JSENGINE)) sed -e 's|$$srcdir|./$(SRCDIR)|g' $(SRCDIR)binding.gyp.in > binding.gyp - $(NODEGYP) --loglevel=silent configure build 1>>/dev/null + MAKEFLAGS= $(NODEGYP) --loglevel=silent configure build 1>>/dev/null else $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) $(JSINCLUDES) $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) @@ -805,45 +805,6 @@ android_clean: rm -f `find $(PACKAGEDIR) -name \*.java | grep -v $(PROJECTNAME).java` rm -rf obj -################################################################## -##### MODULA3 ###### -################################################################## - -MODULA3_INCLUDE= @MODULA3INC@ - -# ---------------------------------------------------------------- -# Build a modula3 dynamically loadable module (C) -# ---------------------------------------------------------------- - -modula3: $(SRCDIR_SRCS) - $(SWIG) -modula3 $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - -modula3_cpp: $(SRCDIR_SRCS) - $(SWIG) -modula3 -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - -# ----------------------------------------------------------------- -# Run modula3 example -# ----------------------------------------------------------------- - -modula3_run: - $(RUNTOOL) false $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -modula3_version: - echo "Unknown modula3 version" - -# ----------------------------------------------------------------- -# Cleaning the modula3 examples -# ----------------------------------------------------------------- - -modula3_clean: - rm -f *_wrap* *.i3 *.m3 - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ - ################################################################## ##### MZSCHEME ###### ################################################################## @@ -852,7 +813,7 @@ MZSCHEME = mzscheme MZC = @MZC@ MZDYNOBJ = @MZDYNOBJ@ MZSCHEME_SO = @MZSCHEME_SO@ -MZSCHEME_SCRIPT = $(RUNME).scm +MZSCHEME_SCRIPT = $(SRCDIR)$(RUNME).scm # ---------------------------------------------------------------- # Build a C/C++ dynamically loadable module @@ -860,12 +821,12 @@ MZSCHEME_SCRIPT = $(RUNME).scm mzscheme: $(SRCDIR_SRCS) $(SWIG) -mzscheme $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(COMPILETOOL) $(MZC) `echo $(INCLUDES) | sed 's/-I/++ccf -I/g'` --cc $(ISRCS) $(SRCDIR_SRCS) + $(COMPILETOOL) $(MZC) `echo " $(CPPFLAGS) $(INCLUDES) $(CFLAGS)" | sed 's/ -/ ++ccf -/g'` --cc $(ISRCS) $(SRCDIR_SRCS) $(COMPILETOOL) $(MZC) --ld $(TARGET)$(MZSCHEME_SO) $(OBJS) $(IOBJS) mzscheme_cpp: $(SRCDIR_SRCS) $(SWIG) -mzscheme -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(COMPILETOOL) $(MZC) `echo $(INCLUDES) | sed 's/-I/++ccf -I/g'` --cc $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) + env CFLAGS= $(COMPILETOOL) $(MZC) `echo " $(CPPFLAGS) $(INCLUDES) $(CXXFLAGS)" | sed 's/ -/ ++ccf -/g'` --cc $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(CXXSHARED) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $(LIBPREFIX)$(TARGET)$(MZSCHEME_SO) $(OBJS) $(IOBJS) $(MZDYNOBJ) $(CPP_DLLIBS) # ----------------------------------------------------------------- @@ -896,135 +857,88 @@ mzscheme_clean: ##### Ocaml ##### ################################################################## -OCC=@OCAMLC@ -OCAMLDLGEN=@OCAMLDLGEN@ -OCAMLFIND=@OCAMLFIND@ -OCAMLMKTOP=@OCAMLMKTOP@ $(SWIGWHERE) +OCC=$(COMPILETOOL) @OCAMLC@ +OCC_WITH_PP=env TMPDIR=./localtmp $(OCC) +# TMPDIR above is a workaround for some ocamlc versions, such as 4.05.0, which always create a temp file of the same name breaking parallel make (seemingly only when -pp is used) +OCAMLDLGEN=$(COMPILETOOL) @OCAMLDLGEN@ +OCAMLFIND=$(COMPILETOOL) @OCAMLFIND@ +OCAMLMKTOP=$(COMPILETOOL) @OCAMLMKTOP@ NOLINK ?= false OCAMLPP= -pp "camlp4o ./swigp4.cmo" OCAMLP4WHERE=`$(COMPILETOOL) @CAMLP4@ -where` -OCAMLCORE=\ - rm -rf swig.mli swig.ml swigp4.ml && \ - $(SWIG) -ocaml -co swig.mli 2>/dev/null && \ - $(SWIG) -ocaml -co swig.ml 2>/dev/null && \ - $(SWIG) -ocaml -co swigp4.ml 2>/dev/null && \ - $(OCC) -c swig.mli && \ - $(OCC) -c swig.ml && \ - $(OCC) -I $(OCAMLP4WHERE) -pp "camlp4o pa_extend.cmo q_MLast.cmo" \ - -c swigp4.ml + +ocaml_core: + mkdir -p ./localtmp + $(SWIG) -ocaml -co swig.mli 2>/dev/null + $(SWIG) -ocaml -co swig.ml 2>/dev/null + $(SWIG) -ocaml -co swigp4.ml 2>/dev/null + $(OCC) -c swig.mli + $(OCC) -c swig.ml + $(OCC_WITH_PP) -I $(OCAMLP4WHERE) -pp "camlp4o pa_extend.cmo q_MLast.cmo" -c swigp4.ml ocaml_static: $(SRCDIR_SRCS) - $(OCAMLCORE) $(SWIG) -ocaml $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) $(OCC) -g -c -ccopt -g -ccopt "$(INCLUDES)" $(ISRCS) $(SRCDIR_SRCS) $(OCC) -g -c $(INTERFACE:%.i=%.mli) - $(OCC) -g -c $(INTERFACE:%.i=%.ml) - test -z "$(PROGFILE)" || test -f "$(PROGFILE)" && \ - $(OCC) $(OCAMLPP) -c $(PROGFILE) - $(NOLINK) || $(OCC) -g -ccopt -g -cclib -g -custom -o $(TARGET) \ - swig.cmo \ - $(INTERFACE:%.i=%.cmo) \ - $(PROGFILE:%.ml=%.cmo) \ - $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) -cclib "$(LIBS)" + $(OCC) -w -U -g -c $(INTERFACE:%.i=%.ml) + test -z "$(PROGFILE)" || $(OCC_WITH_PP) -o $(PROGFILE:%.ml=%) $(OCAMLPP) -c $(SRCDIR)$(PROGFILE) + $(NOLINK) || $(OCC) -g -ccopt -g -cclib -g -custom -o $(RUNME) swig.cmo $(INTERFACE:%.i=%.cmo) $(PROGFILE:%.ml=%.cmo) $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) -cclib "$(LIBS)" ocaml_dynamic: $(SRCDIR_SRCS) - $(OCAMLCORE) $(SWIG) -ocaml $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) $(OCC) -g -c -ccopt -g -ccopt "$(INCLUDES)" $(ISRCS) $(SRCDIR_SRCS) - $(CXXSHARED) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(CCSHARED) -o $(INTERFACE:%.i=%@SO@) \ - $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) $(LIBS) - $(OCAMLDLGEN) $(INTERFACE:%.i=%.ml) $(INTERFACE:%.i=%@SO@) > \ - $(INTERFACE:%.i=%_dynamic.ml) + $(CXXSHARED) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(CCSHARED) -o $(INTERFACE:%.i=%@SO@) $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) $(LIBS) + $(OCAMLDLGEN) $(INTERFACE:%.i=%.ml) $(INTERFACE:%.i=%@SO@) > $(INTERFACE:%.i=%_dynamic.ml) mv $(INTERFACE:%.i=%_dynamic.ml) $(INTERFACE:%.i=%.ml) rm $(INTERFACE:%.i=%.mli) $(OCAMLFIND) $(OCC) -g -c -package dl $(INTERFACE:%.i=%.ml) - test -z "$(PROGFILE)" || test -f "$(PROGFILE)" && \ - $(OCC) $(OCAMLPP) -c $(PROGFILE) - $(NOLINK) || $(OCAMLFIND) \ - $(OCC) -g -ccopt -g -cclib -g -custom -o $(TARGET) \ - swig.cmo \ - -package dl -linkpkg \ - $(INTERFACE:%.i=%.cmo) $(PROGFILE:%.ml=%.cmo) + test -z "$(PROGFILE)" || $(OCC_WITH_PP) -o $(PROGFILE:%.ml=%) $(OCAMLPP) -c $(SRCDIR)$(PROGFILE) + $(NOLINK) || $(OCAMLFIND) $(OCC) -g -ccopt -g -cclib -g -custom -o $(RUNME) swig.cmo -package dl -linkpkg $(INTERFACE:%.i=%.cmo) $(PROGFILE:%.ml=%.cmo) ocaml_static_toplevel: $(SRCDIR_SRCS) - $(OCAMLCORE) $(SWIG) -ocaml $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) $(OCC) -g -c -ccopt -g -ccopt "$(INCLUDES)" $(ISRCS) $(SRCDIR_SRCS) $(OCC) -g -c $(INTERFACE:%.i=%.mli) - $(OCC) -g -c $(INTERFACE:%.i=%.ml) - test -z "$(PROGFILE)" || test -f "$(PROGFILE)" && \ - $(OCC) $(OCAMLPP) -c $(PROGFILE) - $(NOLINK) || $(OCAMLMKTOP) \ - swig.cmo \ - -I $(OCAMLP4WHERE) camlp4o.cma swigp4.cmo \ - -g -ccopt -g -cclib -g -custom -o $(TARGET)_top \ - $(INTERFACE:%.i=%.cmo) \ - $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) -cclib "$(LIBS)" + $(OCC) -w -U -g -c $(INTERFACE:%.i=%.ml) + test -z "$(PROGFILE)" || $(OCC_WITH_PP) -o $(PROGFILE:%.ml=%) $(OCAMLPP) -c $(SRCDIR)$(PROGFILE) + $(NOLINK) || $(OCAMLMKTOP) swig.cmo -I $(OCAMLP4WHERE) dynlink.cma camlp4o.cma swigp4.cmo -cclib "$(LIBS)" -g -ccopt -g -cclib -g -custom -o $(RUNME)_top $(INTERFACE:%.i=%.cmo) $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) ocaml_static_cpp: $(SRCDIR_SRCS) - $(OCAMLCORE) $(SWIG) -ocaml -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) cp $(ICXXSRCS) $(ICXXSRCS:%.cxx=%.c) - $(OCC) -cc '$(CXX) -Wno-write-strings' -g -c -ccopt -g -ccopt "-xc++ $(INCLUDES)" \ - $(ICXXSRCS:%.cxx=%.c) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) + $(OCC) -cc '$(CXX) $(CPPFLAGS)' -g -c -ccopt -g -ccopt "-xc++ $(INCLUDES)" $(ICXXSRCS:%.cxx=%.c) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(OCC) -g -c $(INTERFACE:%.i=%.mli) - $(OCC) -g -c $(INTERFACE:%.i=%.ml) - test -z "$(PROGFILE)" || test -f "$(PROGFILE)" && \ - $(OCC) $(OCAMLPP) -c $(PROGFILE) - $(NOLINK) || $(OCC) -g -ccopt -g -cclib -g -custom -o $(TARGET) \ - swig.cmo \ - $(INTERFACE:%.i=%.cmo) \ - $(PROGFILE:%.ml=%.cmo) \ - $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) \ - -cclib "$(LIBS)" -cc '$(CXX) -Wno-write-strings' + $(OCC) -w -U -g -c $(INTERFACE:%.i=%.ml) + test -z "$(PROGFILE)" || $(OCC_WITH_PP) -o $(PROGFILE:%.ml=%) $(OCAMLPP) -c $(SRCDIR)$(PROGFILE) + $(NOLINK) || $(OCC) -g -ccopt -g -cclib -g -custom -o $(RUNME) swig.cmo $(INTERFACE:%.i=%.cmo) $(PROGFILE:%.ml=%.cmo) $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) -cclib "$(LIBS)" -cc '$(CXX)' ocaml_static_cpp_toplevel: $(SRCDIR_SRCS) - $(OCAMLCORE) $(SWIG) -ocaml -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) cp $(ICXXSRCS) $(ICXXSRCS:%.cxx=%.c) - $(OCC) -cc '$(CXX) -Wno-write-strings' -g -c -ccopt -g -ccopt "-xc++ $(INCLUDES)" \ - $(ICXXSRCS:%.cxx=%.c) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) + $(OCC) -cc '$(CXX) $(CPPFLAGS)' -g -c -ccopt -g -ccopt "-xc++ $(INCLUDES)" $(ICXXSRCS:%.cxx=%.c) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(OCC) -g -c $(INTERFACE:%.i=%.mli) - $(OCC) -g -c $(INTERFACE:%.i=%.ml) - test -z "$(PROGFILE)" || test -f "$(PROGFILE)" && \ - $(OCC) $(OCAMLPP) -c $(PROGFILE) - $(NOLINK) || $(OCAMLMKTOP) \ - swig.cmo \ - -I $(OCAMLP4WHERE) dynlink.cma camlp4o.cma swigp4.cmo \ - -g -ccopt -g -cclib -g -custom -o $(TARGET)_top \ - $(INTERFACE:%.i=%.cmo) \ - $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) \ - -cclib "$(LIBS)" -cc '$(CXX) -Wno-write-strings' + $(OCC) -w -U -g -c $(INTERFACE:%.i=%.ml) + test -z "$(PROGFILE)" || $(OCC_WITH_PP) -o $(PROGFILE:%.ml=%) $(OCAMLPP) -c $(SRCDIR)$(PROGFILE) + $(NOLINK) || $(OCAMLMKTOP) -cc '$(CXX) $(CPPFLAGS)' swig.cmo -I $(OCAMLP4WHERE) dynlink.cma camlp4o.cma swigp4.cmo -cclib "$(LIBS)" -g -ccopt -g -cclib -g -custom -o $(RUNME)_top $(INTERFACE:%.i=%.cmo) $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) ocaml_dynamic_cpp: $(SRCDIR_SRCS) - $(OCAMLCORE) $(SWIG) -ocaml -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) cp $(ICXXSRCS) $(ICXXSRCS:%.cxx=%.c) - $(OCC) -cc '$(CXX) -Wno-write-strings' -g -c -ccopt -g -ccopt "-xc++ $(INCLUDES)" \ - $(ICXXSRCS:%.cxx=%.c) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) -ccopt -fPIC - $(CXXSHARED) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $(INTERFACE:%.i=%@SO@) \ - $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) \ - $(CPP_DLLIBS) $(LIBS) - $(OCAMLDLGEN) $(INTERFACE:%.i=%.ml) $(INTERFACE:%.i=%@SO@) > \ - $(INTERFACE:%.i=%_dynamic.ml) + $(OCC) -cc '$(CXX) $(CPPFLAGS)' -g -c -ccopt -g -ccopt "-xc++ $(INCLUDES)" $(ICXXSRCS:%.cxx=%.c) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) -ccopt -fPIC + $(CXXSHARED) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $(INTERFACE:%.i=%@SO@) $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) $(CPP_DLLIBS) $(LIBS) + $(OCAMLDLGEN) $(INTERFACE:%.i=%.ml) $(INTERFACE:%.i=%@SO@) > $(INTERFACE:%.i=%_dynamic.ml) mv $(INTERFACE:%.i=%_dynamic.ml) $(INTERFACE:%.i=%.ml) rm $(INTERFACE:%.i=%.mli) $(OCAMLFIND) $(OCC) -g -c -package dl $(INTERFACE:%.i=%.ml) - test -z "$(PROGFILE)" || test -f "$(PROGFILE)" && \ - $(OCC) $(OCAMLPP) -c $(PROGFILE) - $(NOLINK) || $(OCAMLFIND) \ - swig.cmo \ - $(OCC) -cclib -export-dynamic -g -ccopt -g -cclib -g -custom \ - -o $(TARGET) \ - -package dl -linkpkg \ - $(INTERFACE:%.i=%.cmo) $(PROGFILE:%.ml=%.cmo) -cc '$(CXX) -Wno-write-strings' + test -z "$(PROGFILE)" || $(OCC_WITH_PP) -o $(PROGFILE:%.ml=%) $(OCAMLPP) -c $(SRCDIR)$(PROGFILE) + $(NOLINK) || $(OCAMLFIND) swig.cmo $(OCC) -cclib -export-dynamic -g -ccopt -g -cclib -g -custom -o $(RUNME) -package dl -linkpkg $(INTERFACE:%.i=%.cmo) $(PROGFILE:%.ml=%.cmo) -cc '$(CXX)' # ----------------------------------------------------------------- # Run ocaml example # ----------------------------------------------------------------- ocaml_run: - $(RUNTOOL) ./$(TARGET) $(RUNPIPE) + $(RUNTOOL) ./$(RUNME) $(RUNPIPE) # ----------------------------------------------------------------- # Version display @@ -1038,9 +952,10 @@ ocaml_version: # ----------------------------------------------------------------- ocaml_clean: - rm -f *_wrap* *~ .~* *.cmo *.cmi $(MLFILE) $(MLFILE)i swig.mli swig.cmi swig.ml swig.cmo swigp4.ml swigp4.cmo + rm -f *_wrap* *~ .~* *.cmo *.cmi *.mli $(TARGET).ml $(RUNME) $(RUNME)_top swig.ml swigp4.ml rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *@SO@ + rm -rf ./localtmp ################################################################## ##### RUBY ###### @@ -1116,7 +1031,7 @@ ruby_clean: rm -f *.@OBJEXT@ *$(RUBY_SO) ################################################################## -##### PHP ###### +##### PHP7 ###### ################################################################## PHP = @PHP@ @@ -1129,7 +1044,7 @@ PHP_SCRIPT = $(SRCDIR)$(RUNME).php # ------------------------------------------------------------------- php: $(SRCDIR_SRCS) - $(SWIG) -php $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(SWIG) -php7 $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(PHP_INCLUDE) $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(PHP_SO) @@ -1138,7 +1053,7 @@ php: $(SRCDIR_SRCS) # -------------------------------------------------------------------- php_cpp: $(SRCDIR_SRCS) - $(SWIG) -php -cppext cxx -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(SWIG) -php7 -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(PHP_INCLUDE) $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(PHP_SO) @@ -1147,7 +1062,7 @@ php_cpp: $(SRCDIR_SRCS) # ----------------------------------------------------------------- php_run: - $(RUNTOOL) $(PHP) -n -q -d extension_dir=. -d safe_mode=Off $(PHP_SCRIPT) $(RUNPIPE) + $(RUNTOOL) $(PHP) -n -q -d extension_dir=. -d safe_mode=Off -d display_errors=stderr $(PHP_SCRIPT) $(RUNPIPE) # ----------------------------------------------------------------- # Version display @@ -1165,194 +1080,6 @@ php_clean: rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *$(PHP_SO) -################################################################## -##### Pike ###### -################################################################## - -# Make sure these locate your Pike installation -PIKE = pike -PIKE_CFLAGS = @PIKECCDLFLAGS@ -DHAVE_CONFIG_H -PIKE_INCLUDE = @PIKEINCLUDE@ -PIKE_LIB = @PIKELIB@ -PIKE_DLNK = @PIKEDYNAMICLINKING@ -PIKE_LIBOPTS = @PIKELINK@ @LIBS@ $(SYSLIBS) -PIKE_SCRIPT = $(RUNME).pike - -# ---------------------------------------------------------------- -# Build a C dynamically loadable module -# ---------------------------------------------------------------- - -pike: $(SRCDIR_SRCS) - $(SWIG) -pike $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(PIKE_CFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) $(PIKE_INCLUDE) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(PIKE_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - -# ----------------------------------------------------------------- -# Build a C++ dynamically loadable module -# ----------------------------------------------------------------- - -pike_cpp: $(SRCDIR_SRCS) - $(SWIG) -c++ -pike $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(PIKE_CFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) $(PIKE_INCLUDE) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(PIKE_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - -# ----------------------------------------------------------------- -# Build statically linked Pike interpreter -# -# These should only be used in conjunction with the %include embed.i -# library file -# ----------------------------------------------------------------- - -pike_static: $(SRCDIR_SRCS) - $(SWIG) -pike -lembed.i $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(PIKE_CFLAGS) @LINKFORSHARED@ $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) \ - $(PIKE_INCLUDE) $(LIBS) -L$(PIKE_LIB) $(PIKE_LIBOPTS) -o $(TARGET) - -pike_cpp_static: $(SRCDIR_SRCS) - $(SWIG) -c++ -pike -lembed.i $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(PIKE_CFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) \ - $(PIKE_INCLUDE) $(LIBS) -L$(PIKE_LIB) $(PIKE_LIBOPTS) -o $(TARGET) - -# ----------------------------------------------------------------- -# Run pike example -# ----------------------------------------------------------------- - -pike_run: - $(RUNTOOL) $(PIKE) $(PIKE_SCRIPT) $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -pike_version: - $(PIKE) -v 2>&1 | head -n 1 - -# ----------------------------------------------------------------- -# Cleaning the Pike examples -# ----------------------------------------------------------------- - -pike_clean: - rm -f *_wrap* *~ .~* mypike@EXEEXT@ - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ - - -################################################################## -##### Chicken ###### -################################################################## - -CHICKEN = @CHICKEN@ -CHICKEN_CSC = @CHICKEN_CSC@ -CHICKEN_CSI = @CHICKEN_CSI@ -CHICKEN_LIBOPTS = @CHICKENLIB@ $(SYSLIBS) -CHICKEN_SHAREDLIBOPTS = @CHICKENSHAREDLIB@ $(SYSLIBS) -CHICKEN_CFLAGS = @CHICKENOPTS@ -CHICKENOPTS = -quiet -CHICKEN_MAIN = -CHICKEN_SCRIPT = $(RUNME).scm - -# SWIG produces $(ISRCS) (the C wrapper file) -# and $(CHICKEN_GENERATED_SCHEME) (the Scheme wrapper file): -CHICKEN_GENERATED_SCHEME = $(INTERFACE:.i=.scm) -CHICKEN_COMPILED_SCHEME = $(INTERFACE:.i=_chicken.c) -CHICKEN_COMPILED_OBJECT = $(CHICKEN_COMPILED_SCHEME:.c=.@OBJEXT@) - -# flags for the main chicken sources (only used when compiling statically) -CHICKEN_COMPILED_MAIN = $(CHICKEN_MAIN:.scm=_chicken.c) -CHICKEN_COMPILED_MAIN_OBJECT = $(CHICKEN_COMPILED_MAIN:.c=.@OBJEXT@) - -# ----------------------------------------------------------------- -# Build a CHICKEN dynamically loadable module -# ----------------------------------------------------------------- - -# This is the old way to build chicken, but it does not work correctly with exceptions -chicken_direct: $(SRCDIR_SRCS) - $(SWIG) -chicken $(SWIGOPT) $(INCLUDE) $(INTERFACEPATH) - $(CHICKEN) $(CHICKEN_GENERATED_SCHEME) $(CHICKENOPTS) \ - -dynamic -feature chicken-compile-shared \ - -output-file $(CHICKEN_COMPILED_SCHEME) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(CHICKEN_CFLAGS) \ - $(INCLUDES) $(CHICKEN_INCLUDE) $(ISRCS) $(SRCDIR_SRCS) $(CHICKEN_COMPILED_SCHEME) - $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(CHICKEN_COMPILED_OBJECT) $(OBJS) $(IOBJS) \ - $(LIBS) $(CHICKEN_SHAREDLIBOPTS) -o $(LIBPREFIX)$(TARGET)$(SO) - -chicken_direct_cpp: $(SRCDIR_CXXSRCS) $(CHICKSRCS) - $(SWIG) -c++ -chicken $(SWIGOPT) $(INCLUDE) $(INTERFACEPATH) - $(CHICKEN) $(CHICKEN_GENERATED_SCHEME) $(CHICKENOPTS) \ - -dynamic -feature chicken-compile-shared \ - -output-file $(CHICKEN_COMPILED_SCHEME) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(CHICKEN_CFLAGS) \ - $(INCLUDES) $(CHICKEN_INCLUDE) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(CHICKEN_COMPILED_SCHEME) - $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(CHICKEN_COMPILED_OBJECT) $(OBJS) $(IOBJS) \ - $(LIBS) $(CPP_DLLIBS) $(CHICKEN_SHAREDLIBOPTS) -o $(LIBPREFIX)$(TARGET)$(SO) - -# ----------------------------------------------------------------- -# Build statically linked CHICKEN interpreter -# ----------------------------------------------------------------- - -# The following two targets are also used by the test suite -chicken_static: $(SRCDIR_SRCS) $(CHICKSRCS) - $(SWIG) -chicken $(SWIGOPT) $(INCLUDE) $(INTERFACEPATH) - $(CHICKEN) $(CHICKEN_GENERATED_SCHEME) $(CHICKENOPTS) \ - -output-file $(CHICKEN_COMPILED_SCHEME) - $(CHICKEN) $(CHICKEN_MAIN) $(CHICKENOPTS) \ - -output-file $(CHICKEN_MAIN:.scm=_chicken.c) - $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(CHICKEN_CFLAGS) \ - $(INCLUDES) $(CHICKEN_INCLUDE) $(ISRCS) $(SRCDIR_SRCS) \ - $(CHICKEN_COMPILED_SCHEME) $(CHICKEN_COMPILED_MAIN) - $(CC) $(CFLAGS) $(LDFLAGS) $(CHICKEN_COMPILED_OBJECT) $(CHICKEN_COMPILED_MAIN_OBJECT) \ - $(OBJS) $(IOBJS) $(LIBS) $(CHICKEN_SHAREDLIBOPTS) -o $(TARGET) - -chicken_static_cpp: $(SRCDIR_CXXSRCS) $(CHICKSRCS) - $(SWIG) -c++ -chicken $(SWIGOPT) $(INCLUDE) $(INTERFACEPATH) - $(CHICKEN) $(CHICKEN_GENERATED_SCHEME) $(CHICKENOPTS) \ - -output-file $(CHICKEN_COMPILED_SCHEME) - $(CHICKEN) $(CHICKEN_MAIN) $(CHICKENOPTS) \ - -output-file $(CHICKEN_MAIN:.scm=_chicken.c) - $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(CHICKEN_CFLAGS) \ - $(INCLUDES) $(CHICKEN_INCLUDE) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) \ - $(CHICKEN_COMPILED_SCHEME) $(CHICKEN_COMPILED_MAIN) - $(CXX) $(CXXFLAGS) $(LDFLAGS) $(CHICKEN_COMPILED_OBJECT) $(CHICKEN_COMPILED_MAIN_OBJECT) \ - $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) $(CHICKEN_SHAREDLIBOPTS) -o $(TARGET) - -# ---------------------------------------------------------------- -# Build a shared library using csc -# ---------------------------------------------------------------- - -chicken: - $(SWIG) -chicken $(SWIGOPT) $(INCLUDE) $(INTERFACEPATH) - $(COMPILETOOL) $(CHICKEN_CSC) -s `echo $(INCLUDES) | sed 's/-I/-C -I/g'` $(CHICKEN_GENERATED_SCHEME) $(SRCDIR_SRCS) $(ISRCS) -o $(TARGET)$(SO) - -chicken_cpp: - $(SWIG) -c++ -chicken $(SWIGOPT) $(INCLUDE) $(INTERFACEPATH) - $(COMPILETOOL) $(CHICKEN_CSC) -s `echo $(INCLUDES) | sed 's/-I/-C -I/g'` $(CHICKEN_GENERATED_SCHEME) $(SRCDIR_SRCS) $(ICXXSRCS) $(SRCDIR_CXXSRCS) -o $(TARGET)$(SO) - -chicken_externalhdr: - $(SWIG) -chicken -external-runtime $(TARGET) - -# ----------------------------------------------------------------- -# Run CHICKEN example -# ----------------------------------------------------------------- - -chicken_run: - env LD_LIBRARY_PATH=$$PWD $(RUNTOOL) $(CHICKEN_CSI) $(CHICKEN_SCRIPT) $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -chicken_version: - $(CHICKEN) -version | grep -i version - -# ----------------------------------------------------------------- -# Cleaning the CHICKEN examples -# ----------------------------------------------------------------- - -chicken_clean: - rm -f *_wrap* *~ .~* *_chicken* - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ - ################################################################## ##### CSHARP ###### ################################################################## @@ -1367,7 +1094,7 @@ CSHARPCFLAGS = @CSHARPCFLAGS@ CSHARPFLAGS = CSHARPOPTIONS = CSHARPSO = @CSHARPSO@ -CSHARP_RUNME = $(CSHARPCILINTERPRETER) $(CSHARPCILINTERPRETER_FLAGS) ./$(RUNME).exe +CSHARP_RUNME = ./$(RUNME).exe # ---------------------------------------------------------------- # Build a CSharp dynamically loadable module (C) @@ -1405,7 +1132,7 @@ csharp_compile: $(SRCDIR_SRCS) # ----------------------------------------------------------------- csharp_run: - env LD_LIBRARY_PATH=$$PWD $(RUNTOOL) $(CSHARP_RUNME) $(RUNPIPE) + env LD_LIBRARY_PATH=$$PWD $(RUNTOOL) $(CSHARPCILINTERPRETER) $(CSHARPCILINTERPRETER_FLAGS) $(CSHARP_RUNME) $(RUNPIPE) # ----------------------------------------------------------------- # Version display @@ -1547,42 +1274,6 @@ allegrocl_clean: rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *@SO@ -################################################################## -##### CLISP ###### -################################################################## - -CLISP = @CLISPBIN@ -CLISP_SCRIPT=$(RUNME).lisp - -clisp: $(SRCDIR_SRCS) - $(SWIG) -clisp $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) - -clisp_cpp: $(SRCDIR_SRCS) - $(SWIG) -c++ -clisp $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) - -# ----------------------------------------------------------------- -# Run CLISP example -# ----------------------------------------------------------------- - -clisp_run: - $(RUNTOOL) $(CLISP) -batch -s $(CLISP_SCRIPT) $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -clisp_version: - $(CLISP) --version | head -n 1 - -# ----------------------------------------------------------------- -# Cleaning the CLISP examples -# ----------------------------------------------------------------- - -clisp_clean: - rm -f *_wrap* *~ .~* - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ - ################################################################## ##### CFFI ###### ################################################################## @@ -1623,46 +1314,6 @@ cffi_clean: rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *@SO@ -################################################################## -##### UFFI ###### -################################################################## - -UFFI = @UFFIBIN@ -UFFI_SCRIPT=$(RUNME).lisp - -uffi: $(SRCDIR_SRCS) - $(SWIG) -uffi $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) -# $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCDIR_SRCS) -# $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - -uffi_cpp: $(SRCDIR_SRCS) - $(SWIG) -c++ -uffi $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) -# $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) -# $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) - -# ----------------------------------------------------------------- -# Run UFFI example -# ----------------------------------------------------------------- - -uffi_run: - $(RUNTOOL) $(UFFI) -batch -s $(UFFI_SCRIPT) $(RUNPIPE) - -# ----------------------------------------------------------------- -# Version display -# ----------------------------------------------------------------- - -uffi_version: - $(UFFI) --version - -# ----------------------------------------------------------------- -# Cleaning the UFFI examples -# ----------------------------------------------------------------- - -uffi_clean: - rm -f *_wrap* *~ .~* - rm -f core @EXTRA_CLEAN@ - rm -f *.@OBJEXT@ *@SO@ - ################################################################## ##### R ###### ################################################################## @@ -1687,7 +1338,7 @@ r: $(SRCDIR_SRCS) ifneq ($(SRCDIR_SRCS),) $(CC) -g -c $(CPPFLAGS) $(CFLAGS) $(R_CFLAGS) $(SRCDIR_SRCS) $(INCLUDES) endif - +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(ISRCS) $(OBJS) > /dev/null ) + +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" PKG_CFLAGS="$(CFLAGS)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(ISRCS) $(OBJS) > /dev/null ) # ---------------------------------------------------------------- # Build a R dynamically loadable module (C++) @@ -1697,7 +1348,7 @@ r_cpp: $(SRCDIR_CXXSRCS) ifneq ($(SRCDIR_CXXSRCS),) $(CXX) -g -c $(CPPFLAGS) $(CXXFLAGS) $(R_CFLAGS) $(SRCDIR_CXXSRCS) $(INCLUDES) endif - +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(RCXXSRCS) $(OBJS) > /dev/null ) + +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" PKG_CXXFLAGS="$(CXXFLAGS)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(RCXXSRCS) $(OBJS) > /dev/null ) # ----------------------------------------------------------------- # Run R example @@ -1864,7 +1515,8 @@ GOPACK = `if $(GO1) ; then echo go tool pack; else echo gopack; fi` GOPACKAGE = $(notdir $(INTERFACE:.i=.a)) -GOPATHDIR = gopath/src/$(INTERFACE:.i=) +GOPATHPARENTDIR = gopath/$(GOMOD)/src +GOPATHDIR = $(GOPATHPARENTDIR)/$(INTERFACE:.i=) GOOBJEXT = `if $(GO15); then echo o; else echo $(GOC:c=); fi` GOGCOBJS = $(GOSRCS:.go=.$(GOOBJEXT)) @@ -1874,8 +1526,18 @@ GOGCCOBJS = $(GOSRCS:.go=.@OBJEXT@) # Build a Go module (C) # ---------------------------------------------------------------- +$(GOPATHPARENTDIR)/go.mod: + @mkdir gopath 2>/dev/null || true + @mkdir gopath/$(GOMOD) 2>/dev/null || true + @mkdir gopath/$(GOMOD)/src 2>/dev/null || true + @mkdir $(GOPATHDIR) 2>/dev/null || true + echo "module swigtests" > $(GOPATHDIR)/go.mod + echo "" >> $(GOPATHDIR)/go.mod + echo "go 1.12" >> $(GOPATHDIR)/go.mod + mv -f $(GOPATHDIR)/go.mod $(GOPATHPARENTDIR)/go.mod + go_nocgo: $(SRCDIR_SRCS) - $(SWIG) -go $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(SWIG) -go -no-cgo $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) if $(GO12) || $(GO13) || $(GO15) || $(GOGCC); then \ $(CC) -g -c $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES); \ else \ @@ -1910,11 +1572,12 @@ go_nocgo: $(SRCDIR_SRCS) fi; \ fi -go: $(SRCDIR_SRCS) - $(SWIG) -go -cgo $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) +go: $(SRCDIR_SRCS) $(GOPATHPARENTDIR)/go.mod + $(SWIG) -go -import-prefix swigtests $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) @mkdir gopath 2>/dev/null || true - @mkdir gopath/src 2>/dev/null || true - @mkdir gopath/src/$(INTERFACE:.i=) 2>/dev/null || true + @mkdir gopath/$(GOMOD) 2>/dev/null || true + @mkdir gopath/$(GOMOD)/src 2>/dev/null || true + @mkdir $(GOPATHDIR) 2>/dev/null || true rm -f $(GOPATHDIR)/* cp $(ISRCS) $(GOPATHDIR)/ if test -f $(IWRAP:.i=.h); then \ @@ -1924,7 +1587,7 @@ go: $(SRCDIR_SRCS) cp $(SRCDIR_SRCS) $(GOPATHDIR)/; \ fi cp $(GOSRCS) $(GOPATHDIR)/ - GOPATH=`pwd`/gopath; \ + GOPATH=`pwd`/gopath/$(GOMOD); \ export GOPATH; \ CGO_CPPFLAGS="$(CPPFLAGS) $(INCLUDES) -I `cd $(SRCDIR) && pwd` -I `pwd`"; \ export CGO_CPPFLAGS; \ @@ -1933,17 +1596,16 @@ go: $(SRCDIR_SRCS) CGO_LDFLAGS="$(LDFLAGS) -lm"; \ export CGO_LDFLAGS; \ (cd $(GOPATHDIR)/ && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o $(GOPACKAGE)) - cp $(GOPATHDIR)/$(GOPACKAGE) $(dir $(INTERFACE))/$(GOPACKAGE) if $(GOGCC); then \ - cp $(dir $(INTERFACE))/$(GOPACKAGE) $(dir $(INTERFACE))/$(GOPACKAGE:.a=.gox); \ + cp $(GOPATHDIR)/$(GOPACKAGE) $(GOPATHDIR)/$(GOPACKAGE:.a=.gox); \ fi if test -f $(SRCDIR)$(RUNME).go; then \ if $(GOGCC) ; then \ - $(COMPILETOOL) $(GCCGO) -c -g $(SRCDIR)$(RUNME).go; \ - $(COMPILETOOL) $(GCCGO) -o $(RUNME) $(RUNME).@OBJEXT@ $(dir $(INTERFACE))/$(GOPACKAGE); \ + $(COMPILETOOL) $(GCCGO) -c -g -I $(GOPATHDIR) $(SRCDIR)$(RUNME).go; \ + $(COMPILETOOL) $(GCCGO) -o $(RUNME) $(RUNME).@OBJEXT@ $(GOPATHDIR)/$(GOPACKAGE); \ elif $(GO12) || $(GO13) || $(GO15); then \ - $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -o $(RUNME).$(GOOBJEXT) $(SRCDIR)$(RUNME).go; \ - $(COMPILETOOL) $(GOTOOL) $(GOLD) -linkmode external -extld "$(CC)" -extldflags "$(CFLAGS) $(LDFLAGS)" -o $(RUNME) $(RUNME).$(GOOBJEXT); \ + $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I $(GOPATHDIR) -o $(RUNME).$(GOOBJEXT) $(SRCDIR)$(RUNME).go; \ + $(COMPILETOOL) $(GOTOOL) $(GOLD) -L $(GOPATHDIR) -linkmode external -extld "$(CC)" -extldflags "$(CFLAGS) $(LDFLAGS)" -o $(RUNME) $(RUNME).$(GOOBJEXT); \ else \ $(COMPILETOOL) $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \ $(COMPILETOOL) $(GOTOOL) $(GOLD) -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $(RUNME) $(RUNME).$(GOOBJEXT); \ @@ -1955,7 +1617,7 @@ go: $(SRCDIR_SRCS) # ---------------------------------------------------------------- go_cpp_nocgo: $(SRCDIR_SRCS) - $(SWIG) -go -c++ $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(SWIG) -go -c++ -no-cgo $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) if $(GO12) || $(GO13) || $(GO15) || $(GOGCC); then \ if test -n "$(SRCDIR_CXXSRCS)$(SRCDIR_SRCS)"; then \ $(CXX) -g -c $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_CXXSRCS) $(SRCDIR_SRCS) $(INCLUDES); \ @@ -2002,11 +1664,12 @@ go_cpp_nocgo: $(SRCDIR_SRCS) fi; \ fi -go_cpp: $(SRCDIR_SRCS) - $(SWIG) -go -c++ -cgo $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) +go_cpp: $(SRCDIR_SRCS) $(GOPATHPARENTDIR)/go.mod + $(SWIG) -go -c++ -import-prefix swigtests $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) @mkdir gopath 2>/dev/null || true - @mkdir gopath/src 2>/dev/null || true - @mkdir gopath/src/$(INTERFACE:.i=) 2>/dev/null || true + @mkdir gopath/$(GOMOD) 2>/dev/null || true + @mkdir gopath/$(GOMOD)/src 2>/dev/null || true + @mkdir $(GOPATHDIR) 2>/dev/null || true rm -f $(GOPATHDIR)/* cp $(ICXXSRCS) $(GOPATHDIR)/ if test -f $(IWRAP:.i=.h); then \ @@ -2019,7 +1682,7 @@ go_cpp: $(SRCDIR_SRCS) cp $(SRCDIR_SRCS) $(GOPATHDIR)/; \ fi cp $(GOSRCS) $(GOPATHDIR)/ - GOPATH=`pwd`/gopath; \ + GOPATH=`pwd`/gopath/$(GOMOD); \ export GOPATH; \ CGO_CPPFLAGS="$(CPPFLAGS) $(INCLUDES) -I `cd $(SRCDIR) && pwd` -I `pwd`"; \ export CGO_CPPFLAGS; \ @@ -2030,17 +1693,16 @@ go_cpp: $(SRCDIR_SRCS) CGO_LDFLAGS="$(LDFLAGS) -lm"; \ export CGO_LDFLAGS; \ (cd $(GOPATHDIR) && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o $(GOPACKAGE)) - cp $(GOPATHDIR)/$(GOPACKAGE) $(dir $(INTERFACE))/$(GOPACKAGE) if $(GOGCC); then \ - cp $(dir $(INTERFACE))/$(GOPACKAGE) $(dir $(INTERFACE))/$(GOPACKAGE:.a=.gox); \ + cp $(GOPATHDIR)/$(GOPACKAGE) $(GOPATHDIR)/$(GOPACKAGE:.a=.gox); \ fi if test -f $(SRCDIR)$(RUNME).go; then \ if $(GOGCC) ; then \ - $(COMPILETOOL) $(GCCGO) -g -c $(SRCDIR)$(RUNME).go; \ - $(COMPILETOOL) $(GCCGO) -o $(RUNME) $(RUNME).@OBJEXT@ $(dir $(INTERFACE))/$(GOPACKAGE) -lstdc++; \ + $(COMPILETOOL) $(GCCGO) -g -c -I $(GOPATHDIR) $(SRCDIR)$(RUNME).go; \ + $(COMPILETOOL) $(GCCGO) -o $(RUNME) $(RUNME).@OBJEXT@ $(GOPATHDIR)/$(GOPACKAGE) -lstdc++; \ elif $(GO12) || $(GO13) || $(GO15); then \ - $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -o $(RUNME).$(GOOBJEXT) $(SRCDIR)$(RUNME).go; \ - $(COMPILETOOL) $(GOTOOL) $(GOLD) -linkmode external -extld "$(CXX)" -extldflags "$(CXXFLAGS) $(LDFLAGS)" -o $(RUNME) $(RUNME).$(GOOBJEXT); \ + $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I $(GOPATHDIR) -o $(RUNME).$(GOOBJEXT) $(SRCDIR)$(RUNME).go; \ + $(COMPILETOOL) $(GOTOOL) $(GOLD) -L $(GOPATHDIR) -linkmode external -extld "$(CXX)" -extldflags "$(CXXFLAGS) $(LDFLAGS)" -o $(RUNME) $(RUNME).$(GOOBJEXT); \ else \ $(COMPILETOOL) $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \ $(COMPILETOOL) $(GOTOOL) $(GOLD) -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $(RUNME) $(RUNME).$(GOOBJEXT); \ diff --git a/Examples/go/callback/gocallback.go b/Examples/go/callback/gocallback.go index 20fd0627a..881f505e0 100644 --- a/Examples/go/callback/gocallback.go +++ b/Examples/go/callback/gocallback.go @@ -36,6 +36,6 @@ func DeleteGoCallback(p GoCallback) { p.deleteCallback() } -func (p *goCallback) Run() { +func (p *overwrittenMethodsOnCallback) Run() { fmt.Println("GoCallback.Run") } diff --git a/Examples/go/callback/runme.go b/Examples/go/callback/runme.go index 03ab0c5e2..2c1d81343 100644 --- a/Examples/go/callback/runme.go +++ b/Examples/go/callback/runme.go @@ -1,8 +1,9 @@ package main import ( - . "./example" "fmt" + + . "example" ) func main() { diff --git a/Examples/go/class/runme.go b/Examples/go/class/runme.go index 8d68afb61..d2f292ed4 100644 --- a/Examples/go/class/runme.go +++ b/Examples/go/class/runme.go @@ -3,8 +3,9 @@ package main import ( - . "./example" "fmt" + + . "example" ) func main() { diff --git a/Examples/go/constants/runme.go b/Examples/go/constants/runme.go index 1427997a0..d56fd62c8 100644 --- a/Examples/go/constants/runme.go +++ b/Examples/go/constants/runme.go @@ -1,8 +1,9 @@ package main import ( - "./example" "fmt" + + "example" ) func main() { diff --git a/Examples/go/director/director.go b/Examples/go/director/director.go index 4f99bfc6d..c70606af1 100644 --- a/Examples/go/director/director.go +++ b/Examples/go/director/director.go @@ -32,7 +32,7 @@ type overwrittenMethodsOnFooBarAbstract struct { fb FooBarAbstract // If additional constructor arguments have been given they are typically - // stored here so that the overriden methods can use them. + // stored here so that the overridden methods can use them. } func (om *overwrittenMethodsOnFooBarAbstract) Foo() string { @@ -59,7 +59,7 @@ func NewFooBarGo() FooBarGo { // The memory of the FooBarAbstract director object instance can be // automatically freed once the FooBarGo instance is garbage collected by // uncommenting the following line. Please make sure to understand the - // runtime.SetFinalizer specific gotchas before doing this. Furthemore + // runtime.SetFinalizer specific gotchas before doing this. Furthermore // DeleteFooBarGo should be deleted if a finalizer is in use or the fooBarGo // struct needs additional data to prevent double deletion. // runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract) diff --git a/Examples/go/director/runme.go b/Examples/go/director/runme.go index 0d839bc88..0e0da07bd 100644 --- a/Examples/go/director/runme.go +++ b/Examples/go/director/runme.go @@ -1,9 +1,10 @@ package main import ( - "./example" "fmt" "os" + + "example" ) func Compare(name string, got string, exp string) error { diff --git a/Examples/go/enum/runme.go b/Examples/go/enum/runme.go index 99d2651f4..50887056e 100644 --- a/Examples/go/enum/runme.go +++ b/Examples/go/enum/runme.go @@ -1,8 +1,9 @@ package main import ( - . "./example" "fmt" + + . "example" ) func main() { diff --git a/Examples/go/extend/runme.go b/Examples/go/extend/runme.go index a56968937..af64a6e5d 100644 --- a/Examples/go/extend/runme.go +++ b/Examples/go/extend/runme.go @@ -3,8 +3,9 @@ package main import ( - . "./example" "fmt" + + . "example" ) func main() { diff --git a/Examples/go/funcptr/runme.go b/Examples/go/funcptr/runme.go index 44dae3c9e..4b20db4fb 100644 --- a/Examples/go/funcptr/runme.go +++ b/Examples/go/funcptr/runme.go @@ -1,8 +1,9 @@ package main import ( - . "./example" "fmt" + + . "example" ) func main() { diff --git a/Examples/go/multimap/runme.go b/Examples/go/multimap/runme.go index 390205a80..571fac7c2 100644 --- a/Examples/go/multimap/runme.go +++ b/Examples/go/multimap/runme.go @@ -1,8 +1,9 @@ package main import ( - . "./example" "fmt" + + . "example" ) func main() { diff --git a/Examples/go/pointer/runme.go b/Examples/go/pointer/runme.go index 1414d341e..0cf340f51 100644 --- a/Examples/go/pointer/runme.go +++ b/Examples/go/pointer/runme.go @@ -1,8 +1,9 @@ package main import ( - . "./example" "fmt" + + . "example" ) func main() { diff --git a/Examples/go/reference/runme.go b/Examples/go/reference/runme.go index 004a04c2e..9999733b3 100644 --- a/Examples/go/reference/runme.go +++ b/Examples/go/reference/runme.go @@ -3,8 +3,9 @@ package main import ( - . "./example" "fmt" + + . "example" ) func main() { diff --git a/Examples/go/simple/runme.go b/Examples/go/simple/runme.go index 9eb0ff454..0bd4657f9 100644 --- a/Examples/go/simple/runme.go +++ b/Examples/go/simple/runme.go @@ -1,8 +1,9 @@ package main import ( - "./example" "fmt" + + "example" ) func main() { diff --git a/Examples/go/template/runme.go b/Examples/go/template/runme.go index fca2f1b75..347795377 100644 --- a/Examples/go/template/runme.go +++ b/Examples/go/template/runme.go @@ -3,8 +3,9 @@ package main import ( - . "./example" "fmt" + + . "example" ) func main() { diff --git a/Examples/go/variables/runme.go b/Examples/go/variables/runme.go index 3d9737f5c..e2dd0c67f 100644 --- a/Examples/go/variables/runme.go +++ b/Examples/go/variables/runme.go @@ -3,8 +3,9 @@ package main import ( - "./example" "fmt" + + "example" ) func main() { diff --git a/Examples/guile/matrix/runme.scm b/Examples/guile/matrix/runme.scm index f11061e56..b898bb485 100644 --- a/Examples/guile/matrix/runme.scm +++ b/Examples/guile/matrix/runme.scm @@ -1,6 +1,3 @@ -#!./matrix \ --e do-test -s -!# ;;; Authors: David Beazley , 1999 ;;; Martin Froehlich , 2000 ;;; @@ -15,7 +12,7 @@ ;;; Explanation: The three lines at the beginning of this script are ;;; telling the kernel to load the enhanced guile interpreter named ;;; "matrix"; to execute the function "do-test" (-e option) after loading -;;; this script (-s option). There are a lot more options wich allow for +;;; this script (-s option). There are a lot more options which allow for ;;; even finer tuning. SEE ALSO: Section "Guile Scripts" in the "Guile ;;; reference manual -- Part I: Preliminaries". ;;; diff --git a/Examples/guile/multivalue/example.i b/Examples/guile/multivalue/example.i index 135389487..0ef710132 100644 --- a/Examples/guile/multivalue/example.i +++ b/Examples/guile/multivalue/example.i @@ -15,14 +15,14 @@ back to this behavior, use: */ void divide_l(int a, int b, int *OUTPUT, int *OUTPUT); -/* Multiple values as vectors. By issueing: */ +/* Multiple values as vectors. By issuing: */ %values_as_vector; /* vectors instead of lists will be used. */ void divide_v(int a, int b, int *OUTPUT, int *OUTPUT); /* Multiple values for multiple-value continuations. - (This is the most elegant way.) By issueing: */ + (This is the most elegant way.) By issuing: */ %multiple_values; /* multiple values are passed to the multiple-value continuation, as created by `call-with-values' or the diff --git a/Examples/guile/simple/example.c b/Examples/guile/simple/example.c index dcafc4dc4..1c2af789c 100644 --- a/Examples/guile/simple/example.c +++ b/Examples/guile/simple/example.c @@ -1,21 +1,18 @@ -/* Simple example from documentation */ /* File : example.c */ -#include +/* A global variable */ +double Foo = 3.0; -double My_variable = 3.0; - -int fact(int n) { - if (n <= 1) return 1; - else return n*fact(n-1); +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; } -int mod(int n, int m) { - return (n % m); -} -char *get_time() { - long ltime; - time(<ime); - return ctime(<ime); -} diff --git a/Examples/guile/simple/example.i b/Examples/guile/simple/example.i index 1a9930a14..4fcea98b2 100644 --- a/Examples/guile/simple/example.i +++ b/Examples/guile/simple/example.i @@ -5,10 +5,8 @@ %} %inline %{ -extern double My_variable; -extern int fact(int); -extern int mod(int n, int m); -extern char *get_time(); +extern int gcd(int x, int y); +extern double Foo; %} %include guile/guilemain.i diff --git a/Examples/guile/simple/runme.scm b/Examples/guile/simple/runme.scm index c3fd0b41f..ccd755701 100644 --- a/Examples/guile/simple/runme.scm +++ b/Examples/guile/simple/runme.scm @@ -3,24 +3,20 @@ (for-each display args) (newline)) -(mdisplay-newline (get-time) "My variable = " (My-variable)) +; Call our gcd() function -(do ((i 0 (1+ i))) - ((= 14 i)) - (mdisplay-newline i " factorial is " (fact i))) +(define x 42) +(define y 105) +(define g (gcd x y)) +(mdisplay-newline "The gcd of " x " and " y " is " g) -(define (mods i imax j jmax) - (if (< i imax) - (if (< j jmax) - (begin - (My-variable (+ (My-variable) (mod i j))) - (mods i imax (+ j 1) jmax)) - (mods (+ i 1) imax 1 jmax)))) +; Manipulate the Foo global variable -(mods 1 150 1 150) +; Output its current value +(mdisplay-newline "Foo = " (Foo)) -(mdisplay-newline "My-variable = " (My-variable)) - -(exit (and (= 1932053504 (fact 13)) - (= 745470.0 (My-variable)))) +; Change its value +(Foo 3.1415926) +; See if the change took effect +(mdisplay-newline "Foo = " (Foo)) diff --git a/Examples/guile/std_vector/example.h b/Examples/guile/std_vector/example.h index 4f0dac70d..52e260d6d 100644 --- a/Examples/guile/std_vector/example.h +++ b/Examples/guile/std_vector/example.h @@ -17,9 +17,8 @@ std::vector half(const std::vector& v) { } void halve_in_place(std::vector& v) { - // would you believe this is the same as the above? - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::vector::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } diff --git a/Examples/java/check.list b/Examples/java/check.list index 825d04a6d..c30550a1c 100644 --- a/Examples/java/check.list +++ b/Examples/java/check.list @@ -2,6 +2,7 @@ callback class constants +doxygen enum extend funcptr diff --git a/Examples/java/doxygen/Makefile b/Examples/java/doxygen/Makefile new file mode 100644 index 000000000..9f471746e --- /dev/null +++ b/Examples/java/doxygen/Makefile @@ -0,0 +1,21 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = -doxygen +JAVASRCS = *.java + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' java_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' java_cpp + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' JAVASRCS='$(JAVASRCS)' JAVAFLAGS='$(JAVAFLAGS)' java_compile + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' java_clean + rm -rf javadocs diff --git a/Examples/java/doxygen/example.cxx b/Examples/java/doxygen/example.cxx new file mode 100644 index 000000000..ccdb87dfe --- /dev/null +++ b/Examples/java/doxygen/example.cxx @@ -0,0 +1,48 @@ +/* File : example.cxx */ + +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +Circle::Circle(double r) : radius(r) { + NumCircles++; +} + +double Circle::area() { + return M_PI*radius*radius; +} + +double Circle::perimeter() { + return 2*M_PI*radius; +} + +Square::Square(double w) : width(w) { + NumSquares++; +} + +double Square::area() { + return width*width; +} + +double Square::perimeter() { + return 4*width; +} + +int NumSquares = 0; +int NumCircles = 0; + +Square MakeSquare(double r) { + return Square(r); +} + +Circle MakeCircle(double w) { + return Circle(w); +} + diff --git a/Examples/java/doxygen/example.dsp b/Examples/java/doxygen/example.dsp new file mode 100644 index 000000000..f52544b95 --- /dev/null +++ b/Examples/java/doxygen/example.dsp @@ -0,0 +1,162 @@ +# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=example - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "example.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "example - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "example - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "example - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "$(JAVA_INCLUDE)" /I "$(JAVA_INCLUDE)\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Java compile post-build step +PostBuild_Cmds=echo on "%JAVA_BIN%\javac" *.java +# End Special Build Tool + +!ELSEIF "$(CFG)" == "example - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "$(JAVA_INCLUDE)" /I "$(JAVA_INCLUDE)\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /machine:I386 /out:"example.dll" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Java compile post-build step +PostBuild_Cmds=echo on "%JAVA_BIN%\javac" *.java +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "example - Win32 Debug" +# Name "example - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\example.cxx +# End Source File +# Begin Source File + +SOURCE=.\example_wrap.cxx +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\example.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=.\example.i + +!IF "$(CFG)" == "example - Win32 Debug" + +# Begin Custom Build +InputPath=.\example.i +InputName=example + +"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + echo In order to function correctly, please ensure the following environment variables are correctly set: + echo JAVA_INCLUDE: %JAVA_INCLUDE% + echo JAVA_BIN: %JAVA_BIN% + echo on + ..\..\..\swig.exe -c++ -java "$(InputPath)" + +# End Custom Build + +!ELSEIF "$(CFG)" == "example - Win32 Release" + +# Begin Custom Build +InputPath=.\example.i +InputName=example + +"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + echo In order to function correctly, please ensure the following environment variables are correctly set: + echo JAVA_INCLUDE: %JAVA_INCLUDE% + echo JAVA_BIN: %JAVA_BIN% + echo on + ..\..\..\swig.exe -c++ -java "$(InputPath)" + +# End Custom Build + +!ENDIF + +# End Source File +# End Target +# End Project diff --git a/Examples/java/doxygen/example.h b/Examples/java/doxygen/example.h new file mode 100644 index 000000000..203348ae4 --- /dev/null +++ b/Examples/java/doxygen/example.h @@ -0,0 +1,107 @@ +/*! \file example.h +This file provides a simple set of Shape classes. */ + +/*! Base class for all shapes. + \author Bob + */ +class Shape { +public: + /*! Default constructor for creating a Shape */ + Shape() { + nshapes++; + } + /*! Destructor for destroying a Shape */ + virtual ~Shape() { + nshapes--; + } + double x; /*!< x co-ordinate */ + double y; /*!< y co-ordinate */ + void move(double dx, double dy); /*!< Move a shape to a new co-ordinate + \param dx x co-ordinate + \param dy y co-ordinate */ + virtual double area() = 0; /*!< \return the area */ + virtual double perimeter() = 0; /*!< \return the perimeter */ + static int nshapes; /*!< Number of shapes currently in existence */ +}; + +/*! A class for representing a circle. + \author Jack + */ +class Circle : public Shape { +private: + double radius; +public: + /*! Construct a circle + * \param r radius of the circle */ + Circle(double r); + /*! Calculate the area of the circle + * \return calculated area */ + virtual double area(); + /*! Calculate the perimeter of the circle + * \return calculated perimeter of the circle */ + virtual double perimeter(); +}; + +/// A class for representing a square. +class Square : public Shape { +private: + double width; +public: + /** Construct a square + * \param w width of the square */ + Square(double w); + /** Calculate the area of the square + * \return calculated area */ + virtual double area(); + /** Calculate the perimeter of the square + * \return calculated perimeter of the square */ + virtual double perimeter(); +}; + +/// A class for representing a rectangle, templated on the type for the rectangle dimensions +template +class Rectangle : public Shape { +private: + T height; + T width; +public: + /** Construct a rectangle + * \param h height of the rectangle + * \param w width of the rectangle */ + Rectangle(T h, T w) : height(h), width(w) {} + /** Calculate the area of the rectangle + * \return calculated area */ + virtual double area() { return width*height; } + /** Calculate the perimeter of the rectangle + * \return calculated perimeter of the rectangle */ + virtual double perimeter() { return 2*height + 2*width; } +}; + + +/*! Factory function for creating a square + * \param r width of the square + * \return a fully constructed square */ +Square MakeSquare(double r); + +/*! Factory function for creating a circle + * \param w radius of the circle + * \return a fully constructed circle */ +Circle MakeCircle(double w); + +/*! Factory function for creating a rectangle + * \param h height of the rectangle + * \param w width of the rectangle + * \return a fully constructed rectangle */ +template +Rectangle MakeRectangle(T h, T w) { + return Rectangle(h, w); +} + + + +/*! Total number of circles ever created */ +extern int NumCircles; + +/// Total number of squares ever created +extern int NumSquares; + diff --git a/Examples/java/doxygen/example.i b/Examples/java/doxygen/example.i new file mode 100644 index 000000000..803563dd9 --- /dev/null +++ b/Examples/java/doxygen/example.i @@ -0,0 +1,17 @@ +%module example + +%{ +#include "example.h" +%} + +%immutable NumSquares; +%immutable NumCircles; + +%include "example.h" + +/*! - this instantiation uses type int */ +%template(RectangleInt) Rectangle; + +/*! - this instantiation uses type int */ +%template(MakeRectangleInt) MakeRectangle; + diff --git a/Examples/java/doxygen/runme.java b/Examples/java/doxygen/runme.java new file mode 100644 index 000000000..6b7bb3d01 --- /dev/null +++ b/Examples/java/doxygen/runme.java @@ -0,0 +1,63 @@ +// This example shows simple usage of the wrapped Shape classes. +// The main purpose of this example is to show the doxygen comments translation to JavaDoc comments. +// Users should look at the generated .java files and if javadoc is installed and working on your system, +// the generated Java docs can be viewed in a browser by opening the javadocs/index.html file. + +import java.io.*; + +public class runme { + static { + try { + System.loadLibrary("example"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) throws InterruptedException, IOException + { + System.out.println("Creating some objects:"); + Circle c = example.MakeCircle(10); + System.out.println(" Created circle " + c); + Square s = example.MakeSquare(10); + System.out.println(" Created square " + s); + RectangleInt r = example.MakeRectangleInt(10, 20); + System.out.println(" Created rectangle " + r); + + System.out.println("\nHere are some properties of the shapes:"); + Shape[] shapes = {c, s, r}; + for (int i=0; i +#include #ifndef SWIG struct A { }; @@ -16,30 +16,26 @@ public: char msg[256]; }; -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - class Test { public: - int simple() throw(int&) { + int simple() { throw(37); return 1; } - int message() throw(const char *) { + int message() { throw("I died."); return 1; } - int hosed() throw(Exc) { + int hosed() { throw(Exc(42,"Hosed")); return 1; } - int unknown() throw(A*) { + int unknown() { static A a; throw &a; return 1; } - int multi(int x) throw(int, const char *, Exc) { + int multi(int x) { if (x == 1) throw(37); if (x == 2) throw("Bleah!"); if (x == 3) throw(Exc(42,"No-go-diggy-die")); @@ -47,7 +43,3 @@ public: } }; -#if defined(_MSC_VER) - #pragma warning(default: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - diff --git a/Examples/lua/exception/example.i b/Examples/lua/exception/example.i index 6187f8eff..a6b43837d 100644 --- a/Examples/lua/exception/example.i +++ b/Examples/lua/exception/example.i @@ -12,6 +12,12 @@ // note: only works if Exc is copyable %apply SWIGTYPE EXCEPTION_BY_VAL {Exc}; +%catches(int) Test::simple(); +%catches(const char *) Test::message(); +%catches(Exc) Test::hosed(); +%catches(A*) Test::unknown(); +%catches(int, const char *, Exc) Test::multi(int x); + /* Let's just grab the original header file here */ %include "example.h" diff --git a/Examples/lua/exception/runme.lua b/Examples/lua/exception/runme.lua index a798efca7..adb2516c4 100644 --- a/Examples/lua/exception/runme.lua +++ b/Examples/lua/exception/runme.lua @@ -2,7 +2,7 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then - -- lua5.0 doesnt have a nice way to do this + -- lua5.0 doesn't have a nice way to do this lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else @@ -48,7 +48,7 @@ else end -- this is a rather strange way to perform the multiple catch of exceptions -print "calling t:mutli()" +print "calling t:multi()" for i=1,3 do ok,res=pcall(function() t:multi(i) end) if ok then diff --git a/Examples/lua/funcptr3/runme.lua b/Examples/lua/funcptr3/runme.lua index b78c504ef..3cd58520f 100644 --- a/Examples/lua/funcptr3/runme.lua +++ b/Examples/lua/funcptr3/runme.lua @@ -1,6 +1,6 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then - -- lua5.0 doesnt have a nice way to do this + -- lua5.0 doesn't have a nice way to do this lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else diff --git a/Examples/lua/functest/runme.lua b/Examples/lua/functest/runme.lua index 65b3cc215..773ab5dd6 100644 --- a/Examples/lua/functest/runme.lua +++ b/Examples/lua/functest/runme.lua @@ -1,6 +1,6 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then - -- lua5.0 doesnt have a nice way to do this + -- lua5.0 doesn't have a nice way to do this lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else diff --git a/Examples/lua/functor/runme.lua b/Examples/lua/functor/runme.lua index adf124ac6..d6f4d08c7 100644 --- a/Examples/lua/functor/runme.lua +++ b/Examples/lua/functor/runme.lua @@ -1,7 +1,7 @@ -- Operator overloading example ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then - -- lua5.0 doesnt have a nice way to do this + -- lua5.0 doesn't have a nice way to do this lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else diff --git a/Examples/lua/import/runme.lua b/Examples/lua/import/runme.lua index 9cd7ae06c..7057b7bbd 100644 --- a/Examples/lua/import/runme.lua +++ b/Examples/lua/import/runme.lua @@ -3,7 +3,7 @@ print("Testing the %import directive") if string.sub(_VERSION,1,7)=='Lua 5.0' then - -- lua5.0 doesnt have a nice way to do this + -- lua5.0 doesn't have a nice way to do this function loadit(a) lib=loadlib(a..'.dll','luaopen_'..a) or loadlib(a..'.so','luaopen_'..a) assert(lib)() diff --git a/Examples/lua/nspace/runme.lua b/Examples/lua/nspace/runme.lua index 876814052..a894cf849 100644 --- a/Examples/lua/nspace/runme.lua +++ b/Examples/lua/nspace/runme.lua @@ -5,7 +5,7 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then - -- lua5.0 doesnt have a nice way to do this + -- lua5.0 doesn't have a nice way to do this lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else diff --git a/Examples/lua/owner/runme.lua b/Examples/lua/owner/runme.lua index 847645448..4d953cba6 100644 --- a/Examples/lua/owner/runme.lua +++ b/Examples/lua/owner/runme.lua @@ -1,7 +1,7 @@ -- Operator overloading example ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then - -- lua5.0 doesnt have a nice way to do this + -- lua5.0 doesn't have a nice way to do this lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else diff --git a/Examples/lua/pointer/runme.lua b/Examples/lua/pointer/runme.lua index 8deee67e6..2906cc663 100644 --- a/Examples/lua/pointer/runme.lua +++ b/Examples/lua/pointer/runme.lua @@ -1,6 +1,6 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then - -- lua5.0 doesnt have a nice way to do this + -- lua5.0 doesn't have a nice way to do this lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else diff --git a/Examples/lua/simple/runme.lua b/Examples/lua/simple/runme.lua index 1e5a139c8..5f2e95c2f 100644 --- a/Examples/lua/simple/runme.lua +++ b/Examples/lua/simple/runme.lua @@ -1,6 +1,6 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then - -- lua5.0 doesnt have a nice way to do this + -- lua5.0 doesn't have a nice way to do this lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else diff --git a/Examples/lua/variables/runme.lua b/Examples/lua/variables/runme.lua index 05b2d3fbf..826845e90 100644 --- a/Examples/lua/variables/runme.lua +++ b/Examples/lua/variables/runme.lua @@ -1,6 +1,6 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then - -- lua5.0 doesnt have a nice way to do this + -- lua5.0 doesn't have a nice way to do this lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else @@ -54,9 +54,9 @@ example.print_vars() print "\nNow I'm going to try and modify some read only variables"; -print " Tring to set 'path' to 'Whoa!'"; +print " Trying to set 'path' to 'Whoa!'"; if pcall(function() example.path = "Whoa!" end)==true then - print " Thats funny, it didn't give an error!" + print " That's funny, it didn't give an error!" else print " It gave an error, as it should" end @@ -64,7 +64,7 @@ print(" Just checking the value: path =", example.path) print " Trying to set 'status' to '0'"; if pcall(function() example.status = 0 end)==true then - print " Thats funny, it didn't give an error!" + print " That's funny, it didn't give an error!" else print " It gave an error, as it should" end diff --git a/Examples/mzscheme/check.list b/Examples/mzscheme/check.list index f9e4f11c7..d2554c41c 100644 --- a/Examples/mzscheme/check.list +++ b/Examples/mzscheme/check.list @@ -1,4 +1,5 @@ # see top-level Makefile.in +class multimap simple std_vector diff --git a/Examples/mzscheme/class/Makefile b/Examples/mzscheme/class/Makefile new file mode 100644 index 000000000..0b36a60d7 --- /dev/null +++ b/Examples/mzscheme/class/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' mzscheme_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' mzscheme_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' mzscheme_clean diff --git a/Examples/mzscheme/class/example.cxx b/Examples/mzscheme/class/example.cxx new file mode 100644 index 000000000..046304519 --- /dev/null +++ b/Examples/mzscheme/class/example.cxx @@ -0,0 +1,28 @@ +/* File : example.cxx */ + +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area() { + return M_PI*radius*radius; +} + +double Circle::perimeter() { + return 2*M_PI*radius; +} + +double Square::area() { + return width*width; +} + +double Square::perimeter() { + return 4*width; +} diff --git a/Examples/mzscheme/class/example.h b/Examples/mzscheme/class/example.h new file mode 100644 index 000000000..0dff185b2 --- /dev/null +++ b/Examples/mzscheme/class/example.h @@ -0,0 +1,34 @@ +/* File : example.h */ + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + } + double x, y; + void move(double dx, double dy); + virtual double area() = 0; + virtual double perimeter() = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { } + virtual double area(); + virtual double perimeter(); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { } + virtual double area(); + virtual double perimeter(); +}; diff --git a/Examples/mzscheme/class/example.i b/Examples/mzscheme/class/example.i new file mode 100644 index 000000000..fbdf7249f --- /dev/null +++ b/Examples/mzscheme/class/example.i @@ -0,0 +1,9 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" diff --git a/Examples/mzscheme/class/runme.scm b/Examples/mzscheme/class/runme.scm new file mode 100644 index 000000000..dea0b75bc --- /dev/null +++ b/Examples/mzscheme/class/runme.scm @@ -0,0 +1,60 @@ +; file: runme.scm + +; This file illustrates the proxy class C++ interface generated +; by SWIG. + +(load-extension "example.so") + +; Convenience wrapper around the display function +; (which only accepts one argument at the time) + +(define (mdisplay-newline . args) + (for-each display args) + (newline)) + +; ----- Object creation ----- + +(mdisplay-newline "Creating some objects:") +(define c (new-Circle 10)) +(mdisplay-newline " Created circle " c) +(define s (new-Square 10)) +(mdisplay-newline " Created square " s) + +; ----- Access a static member ----- + +(mdisplay-newline "\nA total of " (Shape-nshapes) " shapes were created") + +; ----- Member data access ----- + +; Set the location of the object + +(Shape-x-set c 20) +(Shape-y-set c 30) + +(Shape-x-set s -10) +(Shape-y-set s 5) + +(mdisplay-newline "\nHere is their current position:") +(mdisplay-newline " Circle = (" (Shape-x-get c) "," (Shape-y-get c) ")") +(mdisplay-newline " Square = (" (Shape-x-get s) "," (Shape-y-get s) ")") + +; ----- Call some methods ----- + +(mdisplay-newline "\nHere are some properties of the shapes:") +(define (shape-props o) + (mdisplay-newline " " o) + (mdisplay-newline " area = " (Shape-area o)) + (mdisplay-newline " perimeter = " (Shape-perimeter o))) +(for-each shape-props (list c s)) + +(mdisplay-newline "\nGuess I'll clean up now") + +; Note: this invokes the virtual destructor +(delete-Shape c) +(delete-Shape s) + +(define s 3) +(mdisplay-newline (Shape-nshapes) " shapes remain") +(mdisplay-newline "Goodbye") + +(exit 0) diff --git a/Examples/mzscheme/multimap/Makefile b/Examples/mzscheme/multimap/Makefile index 713ee43a7..eccd59d82 100644 --- a/Examples/mzscheme/multimap/Makefile +++ b/Examples/mzscheme/multimap/Makefile @@ -13,5 +13,6 @@ build: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' mzscheme + clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' mzscheme_clean diff --git a/Examples/mzscheme/multimap/example.c b/Examples/mzscheme/multimap/example.c index b8360fa8a..e945042ab 100644 --- a/Examples/mzscheme/multimap/example.c +++ b/Examples/mzscheme/multimap/example.c @@ -27,7 +27,7 @@ int gcdmain(int argc, char *argv[]) { return 0; } -int count(char *bytes, int len, char c) { +int charcount(char *bytes, int len, char c) { int i; int count = 0; for (i = 0; i < len; i++) { diff --git a/Examples/mzscheme/multimap/example.i b/Examples/mzscheme/multimap/example.i index 515948abc..db4be3d16 100644 --- a/Examples/mzscheme/multimap/example.i +++ b/Examples/mzscheme/multimap/example.i @@ -4,7 +4,7 @@ %{ extern int gcd(int x, int y); extern int gcdmain(int argc, char *argv[]); -extern int count(char *bytes, int len, char c); +extern int charcount(char *bytes, int len, char c); extern void capitalize (char *str, int len); extern void circle (double cx, double cy); extern int squareCubed (int n, int *OUTPUT); @@ -50,7 +50,7 @@ extern int gcdmain(int argc, char *argv[]); $2 = SCHEME_STRLEN_VAL($input); } -extern int count(char *bytes, int len, char c); +extern int charcount(char *bytes, int len, char c); /* This example shows how to wrap a function that mutates a string */ @@ -68,7 +68,7 @@ extern int count(char *bytes, int len, char c); %typemap(argout) (char *str, int len) { Scheme_Object *s; - s = scheme_make_sized_string($1,$2,1); + s = scheme_make_sized_string($1,$2); SWIG_APPEND_VALUE(s); free($1); } diff --git a/Examples/mzscheme/multimap/runme.scm b/Examples/mzscheme/multimap/runme.scm index f1e626f43..6d2c9cce3 100644 --- a/Examples/mzscheme/multimap/runme.scm +++ b/Examples/mzscheme/multimap/runme.scm @@ -20,7 +20,7 @@ (gcdmain #("gcdmain" "42" "105")) -(display (count "Hello World" #\l)) +(display (charcount "Hello World" #\l)) (newline) (display (capitalize "hello world")) diff --git a/Examples/mzscheme/simple/Makefile b/Examples/mzscheme/simple/Makefile index 713ee43a7..eccd59d82 100644 --- a/Examples/mzscheme/simple/Makefile +++ b/Examples/mzscheme/simple/Makefile @@ -13,5 +13,6 @@ build: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' mzscheme + clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' mzscheme_clean diff --git a/Examples/mzscheme/simple/README b/Examples/mzscheme/simple/README deleted file mode 100644 index 07e8da069..000000000 --- a/Examples/mzscheme/simple/README +++ /dev/null @@ -1 +0,0 @@ -Simple example from users manual. diff --git a/Examples/mzscheme/simple/example.c b/Examples/mzscheme/simple/example.c index f2b074781..1c2af789c 100644 --- a/Examples/mzscheme/simple/example.c +++ b/Examples/mzscheme/simple/example.c @@ -1,24 +1,18 @@ -/* Simple example from documentation */ /* File : example.c */ -#include +/* A global variable */ +double Foo = 3.0; -double My_variable = 3.0; - -/* Compute factorial of n */ -int fact(int n) { - if (n <= 1) return 1; - else return n*fact(n-1); -} - -/* Compute n mod m */ -int my_mod(int n, int m) { - return (n % m); +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; } -char *get_time() { - long ltime; - time(<ime); - return ctime(<ime); -} diff --git a/Examples/mzscheme/simple/example.i b/Examples/mzscheme/simple/example.i index 5b3e95580..24093b9bf 100644 --- a/Examples/mzscheme/simple/example.i +++ b/Examples/mzscheme/simple/example.i @@ -1,16 +1,7 @@ /* File : example.i */ %module example -%{ -/* Put headers and other declarations here */ -%} - -%include typemaps.i - -%rename(mod) my_mod; %inline %{ -extern double My_variable; -extern int fact(int); -extern int my_mod(int n, int m); -extern char *get_time(); +extern int gcd(int x, int y); +extern double Foo; %} diff --git a/Examples/mzscheme/simple/runme.scm b/Examples/mzscheme/simple/runme.scm index a98e31fd5..88d32d6fc 100644 --- a/Examples/mzscheme/simple/runme.scm +++ b/Examples/mzscheme/simple/runme.scm @@ -2,23 +2,30 @@ (load-extension "example.so") -(display (get-time)) +; Call our gcd() function -(printf "My-variable = ~a~n" (my-variable)) +(define x 42) +(define y 105) +(define g (gcd x y)) +(display "The gcd of ") +(display x) +(display " and ") +(display y) +(display " is ") +(display g) +(newline) -(let loop ((i 0)) - (when (< i 14) (begin (display i) - (display " factorial is ") - (display (fact i)) - (newline) - (loop (+ i 1))))) +; Manipulate the Foo global variable -(let loop ((i 1)) - (when (< i 250) - (begin - (let loopi ((j 1)) - (when (< j 250) (begin (my-variable (+ (my-variable) (mod i j))) - (loopi (+ j 1))))) - (loop (+ i 1))))) +; Output its current value +(display "Foo = ") +(display (Foo)) +(newline) -(printf "My-variable = ~a~n" (my-variable)) +; Change its value +(Foo 3.1415926) + +; See if the change took effect +(display "Foo = ") +(display (Foo)) +(newline) diff --git a/Examples/mzscheme/std_vector/Makefile b/Examples/mzscheme/std_vector/Makefile index 96f5e80cf..8057465b3 100644 --- a/Examples/mzscheme/std_vector/Makefile +++ b/Examples/mzscheme/std_vector/Makefile @@ -1,21 +1,18 @@ TOP = ../.. SWIGEXE = $(TOP)/../swig SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib -SRCS = +CXXSRCS = TARGET = example INTERFACE = example.i SWIGOPT = -GPP = `which g++` -MZC = test -n "/usr/bin/mzc" && /usr/bin/mzc - check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' mzscheme_run build: - $(SWIGEXE) -mzscheme -c++ $(SWIGOPT) $(INTERFACE) - $(MZC) --compiler $(GPP) ++ccf "-I." --cc example_wrap.cxx - $(MZC) --linker $(GPP) --ld $(TARGET).so example_wrap.o + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' mzscheme_cpp clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' mzscheme_clean diff --git a/Examples/mzscheme/std_vector/example.h b/Examples/mzscheme/std_vector/example.h index 4f0dac70d..52e260d6d 100644 --- a/Examples/mzscheme/std_vector/example.h +++ b/Examples/mzscheme/std_vector/example.h @@ -17,9 +17,8 @@ std::vector half(const std::vector& v) { } void halve_in_place(std::vector& v) { - // would you believe this is the same as the above? - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::vector::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } diff --git a/Examples/mzscheme/std_vector/runme.scm b/Examples/mzscheme/std_vector/runme.scm index 67351f128..7af9d168e 100644 --- a/Examples/mzscheme/std_vector/runme.scm +++ b/Examples/mzscheme/std_vector/runme.scm @@ -9,16 +9,17 @@ (if (< i size) (begin (proc v i) - (with-vector-item v (+ i 1))))) + (with-vector-item v (+ i 1))) + (void))) (with-vector-item v 0))) -(define (with-intvector v proc) - (with-vector v proc intvector-length)) -(define (with-doublevector v proc) - (with-vector v proc doublevector-length)) +(define (with-IntVector v proc) + (with-vector v proc IntVector-length)) +(define (with-DoubleVector v proc) + (with-vector v proc DoubleVector-length)) -(define (print-doublevector v) - (with-doublevector v (lambda (v i) (display (doublevector-ref v i)) +(define (print-DoubleVector v) + (with-DoubleVector v (lambda (v i) (display (DoubleVector-ref v i)) (display " "))) (newline)) @@ -29,11 +30,11 @@ (newline) ; ... or a wrapped std::vector -(define v (new-intvector 4)) -(with-intvector v (lambda (v i) (intvector-set! v i (+ i 1)))) +(define v (new-IntVector 4)) +(with-IntVector v (lambda (v i) (IntVector-set! v i (+ i 1)))) (display (average v)) (newline) -(delete-intvector v) +(delete-IntVector v) ; half will return a Scheme vector. ; Call it with a Scheme vector... @@ -42,13 +43,12 @@ (newline) ; ... or a wrapped std::vector -(define v (new-doublevector)) -(map (lambda (i) (doublevector-push! v i)) '(1 2 3 4)) +(define v (new-DoubleVector)) +(map (lambda (i) (DoubleVector-push! v i)) '(1 2 3 4)) (display (half v)) (newline) ; now halve a wrapped std::vector in place (halve-in-place v) -(print-doublevector v) -(delete-doublevector v) - +(print-DoubleVector v) +(delete-DoubleVector v) diff --git a/Examples/ocaml/argout_ref/Makefile b/Examples/ocaml/argout_ref/Makefile index 8b7fc959e..09370940f 100644 --- a/Examples/ocaml/argout_ref/Makefile +++ b/Examples/ocaml/argout_ref/Makefile @@ -4,8 +4,7 @@ SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib SRCS = example.c TARGET = example INTERFACE = example.i -MLFILE = example.ml -PROGFILE = example_prog.ml +PROGFILE = runme.ml OBJS = example.o check: build @@ -16,16 +15,20 @@ build: static static: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_static_cpp dynamic: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_dynamic_cpp clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' MLFILE='$(MLFILE)' ocaml_clean + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_clean diff --git a/Examples/ocaml/argout_ref/example.i b/Examples/ocaml/argout_ref/example.i index 5ea6777fb..a3e6bf8a6 100644 --- a/Examples/ocaml/argout_ref/example.i +++ b/Examples/ocaml/argout_ref/example.i @@ -1,8 +1,13 @@ /* File : example.i */ %module example +%typemap(argout) (const int &x, const int &y) { + swig_result = caml_list_append(swig_result, caml_val_int(*$1)); + swig_result = caml_list_append(swig_result, caml_val_int(*$2)); +} + %{ -extern "C" void factor(int &x, int &y); +extern "C" void factor(const int &x, const int &y); %} -extern "C" void factor(int &x, int &y); +extern "C" void factor(const int &x, const int &y); diff --git a/Examples/ocaml/argout_ref/example_prog.ml b/Examples/ocaml/argout_ref/example_prog.ml deleted file mode 100644 index c6de34597..000000000 --- a/Examples/ocaml/argout_ref/example_prog.ml +++ /dev/null @@ -1,26 +0,0 @@ -(* example_prog.ml *) - -open Swig -open Example - -exception BadReturn - -let _ = if Array.length Sys.argv < 3 then - begin - print_endline - ("Usage: " ^ Sys.argv.(0) ^ " n1 n2\n" ^ - " Displays the least factors of the numbers that have the same\n" ^ - " relationship, 16 12 -> 4 3\n") ; - exit 0 - end - -let x = int_of_string Sys.argv.(1) -let y = int_of_string Sys.argv.(2) -let (xf,yf) = match _factor '((x to int),(y to int)) with - C_list [ C_int a ; C_int b ] -> a,b - | _ -> raise BadReturn -let _ = print_endline - ("Factorization of " ^ (string_of_int x) ^ - " and " ^ (string_of_int y) ^ - " is " ^ (string_of_int xf) ^ - " and " ^ (string_of_int yf)) diff --git a/Examples/ocaml/argout_ref/runme.ml b/Examples/ocaml/argout_ref/runme.ml new file mode 100644 index 000000000..cb9a94255 --- /dev/null +++ b/Examples/ocaml/argout_ref/runme.ml @@ -0,0 +1,17 @@ +(* runme.ml *) + +open Swig +open Example + +exception BadReturn + +let x = if Array.length Sys.argv > 1 then int_of_string Sys.argv.(1) else 16 +let y = if Array.length Sys.argv > 2 then int_of_string Sys.argv.(2) else 12 +let (xf,yf) = match _factor '((x to int),(y to int)) with + C_list [ C_int a ; C_int b ] -> a,b + | _ -> raise BadReturn +let _ = print_endline + ("Factorization of " ^ (string_of_int x) ^ + " and " ^ (string_of_int y) ^ + " is " ^ (string_of_int xf) ^ + " and " ^ (string_of_int yf)) diff --git a/Examples/ocaml/callback/Makefile b/Examples/ocaml/callback/Makefile new file mode 100644 index 000000000..b81b5ac1b --- /dev/null +++ b/Examples/ocaml/callback/Makefile @@ -0,0 +1,35 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SWIGOPT = +SRCS = example.c +TARGET = example +INTERFACE = example.i +PROGFILE = runme.ml +OBJS = example.o + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_run + +build: static + +static: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ + ocaml_static_cpp + +toplevel: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ + ocaml_static_cpp_toplevel + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_clean diff --git a/Examples/ocaml/callback/example.c b/Examples/ocaml/callback/example.c new file mode 100644 index 000000000..4ead01f58 --- /dev/null +++ b/Examples/ocaml/callback/example.c @@ -0,0 +1,3 @@ +/* File : example.c */ + +#include "example.h" diff --git a/Examples/ocaml/callback/example.h b/Examples/ocaml/callback/example.h new file mode 100644 index 000000000..12d888595 --- /dev/null +++ b/Examples/ocaml/callback/example.h @@ -0,0 +1,20 @@ +/* File : example.h */ + +#include + +class Callback { +public: + virtual ~Callback() { std::cout << "Callback::~Callback()" << std::endl; } + virtual void run() { std::cout << "Callback::run()" << std::endl; } +}; + + +class Caller { + Callback *_callback; +public: + Caller(): _callback(0) {} + ~Caller() { delCallback(); } + void delCallback() { delete _callback; _callback = 0; } + void setCallback(Callback *cb) { delCallback(); _callback = cb; } + void call() { if (_callback) _callback->run(); } +}; diff --git a/Examples/ocaml/callback/example.i b/Examples/ocaml/callback/example.i new file mode 100644 index 000000000..584da73d9 --- /dev/null +++ b/Examples/ocaml/callback/example.i @@ -0,0 +1,10 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +%feature("director") Callback; + +%include "example.h" + diff --git a/Examples/ocaml/callback/runme.ml b/Examples/ocaml/callback/runme.ml new file mode 100644 index 000000000..ddc974984 --- /dev/null +++ b/Examples/ocaml/callback/runme.ml @@ -0,0 +1,30 @@ +(* file: runme.ml + +This file illustrates cross-language polymorphism using directors. *) + +open Swig +open Example + +let new_OCamlCallback ob meth args = + match meth with + | "run" -> print_endline "OCamlCallback.run()"; C_void + | _ -> (invoke ob) meth args + +let caller = new_Caller '() + +let _ = print_endline "Adding and calling a normal C++ callback" +let _ = print_endline "----------------------------------------" + +let callback = new_Callback '() +let _ = caller -> "setCallback" (callback) +let _ = caller -> "call" () +let _ = caller -> "delCallback" () + +let _ = print_endline "\nAdding and calling an OCaml callback" +let _ = print_endline "------------------------------------" + +let callback = new_derived_object new_Callback (new_OCamlCallback) '() +let _ = caller -> "setCallback" (callback) +let _ = caller -> "call" () +let _ = caller -> "delCallback" () +let _ = print_endline "\nOCaml exit" diff --git a/Examples/ocaml/check.list b/Examples/ocaml/check.list index cbdf270f0..cab5a6545 100644 --- a/Examples/ocaml/check.list +++ b/Examples/ocaml/check.list @@ -1,10 +1,13 @@ # see top-level Makefile.in -simple -std_string -std_vector -stl argout_ref -shapes +callback +class contract scoped_enum +shapes +simple +#std_string +std_vector +stl string_from_ptr +strings_test diff --git a/Examples/ocaml/class/Makefile b/Examples/ocaml/class/Makefile new file mode 100644 index 000000000..b81b5ac1b --- /dev/null +++ b/Examples/ocaml/class/Makefile @@ -0,0 +1,35 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SWIGOPT = +SRCS = example.c +TARGET = example +INTERFACE = example.i +PROGFILE = runme.ml +OBJS = example.o + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_run + +build: static + +static: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ + ocaml_static_cpp + +toplevel: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ + ocaml_static_cpp_toplevel + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_clean diff --git a/Examples/ocaml/class/example.c b/Examples/ocaml/class/example.c new file mode 100644 index 000000000..3bac43244 --- /dev/null +++ b/Examples/ocaml/class/example.c @@ -0,0 +1,28 @@ +/* File : example.c */ + +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area() { + return M_PI*radius*radius; +} + +double Circle::perimeter() { + return 2*M_PI*radius; +} + +double Square::area() { + return width*width; +} + +double Square::perimeter() { + return 4*width; +} diff --git a/Examples/ocaml/class/example.h b/Examples/ocaml/class/example.h new file mode 100644 index 000000000..0dff185b2 --- /dev/null +++ b/Examples/ocaml/class/example.h @@ -0,0 +1,34 @@ +/* File : example.h */ + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + } + double x, y; + void move(double dx, double dy); + virtual double area() = 0; + virtual double perimeter() = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { } + virtual double area(); + virtual double perimeter(); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { } + virtual double area(); + virtual double perimeter(); +}; diff --git a/Examples/ocaml/class/example.i b/Examples/ocaml/class/example.i new file mode 100644 index 000000000..fbdf7249f --- /dev/null +++ b/Examples/ocaml/class/example.i @@ -0,0 +1,9 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" diff --git a/Examples/ocaml/class/runme.ml b/Examples/ocaml/class/runme.ml new file mode 100644 index 000000000..5e7b1f26c --- /dev/null +++ b/Examples/ocaml/class/runme.ml @@ -0,0 +1,57 @@ +(* file: runme.ml + + This file illustrates the proxy class C++ interface generated + by SWIG. *) + +open Swig +open Example + +let repr o = + Printf.sprintf "<%s at %#x>" (o -> ":classof" () as string) (o -> "&" () as int) + +(* ----- Object creation ----- *) + +let _ = print_endline "Creating some objects:" +let c = new_Circle '(10) +let _ = Printf.printf " Created circle %s\n" (repr c) +let s = new_Square '(10) +let _ = Printf.printf " Created square %s\n" (repr s) + +(* ----- Access a static member ----- *) + +let _ = Printf.printf "\nA total of %d shapes were created\n" (_Shape_nshapes '() as int) + +(* ----- Member data access ----- *) + +(* Set the location of the object *) + +let _ = c -> "[x]" (20) +let _ = c -> "[y]" (30) + +(* Temp var to work around a swigp4 bug (it doesn't properly handle "-" in some cases). *) +let arg = (-10. to float) +let _ = s -> "[x]" (arg) +let _ = s -> "[y]" (5) + +let _ = print_endline "\nHere is their current position:" +let _ = Printf.printf " Circle = (%f, %f)\n" (c -> "[x]" () as float) (c -> "[y]" () as float) +let _ = Printf.printf " Square = (%f, %f)\n" (s -> "[x]" () as float) (s -> "[y]" () as float) + +(* ----- Call some methods ----- *) + +let _ = print_endline "\nHere are some properties of the shapes:" + +let _ = List.iter (fun o -> + Printf.printf " %s\n" (repr o); + Printf.printf " area = %f\n" (o -> area () as float); + Printf.printf " perimeter = %f\n" (o -> perimeter () as float) + ) [c; s] + +let _ = print_endline "\nGuess I'll clean up now" + +(* Note: this invokes the virtual destructor *) +let _ = c -> "~" () +let _ = s -> "~" () + +let _ = Printf.printf "%d shapes remain\n" (_Shape_nshapes '() as int) +let _ = print_endline "Goodbye" diff --git a/Examples/ocaml/contract/Makefile b/Examples/ocaml/contract/Makefile index c77e6dcc4..8148de142 100644 --- a/Examples/ocaml/contract/Makefile +++ b/Examples/ocaml/contract/Makefile @@ -4,8 +4,7 @@ SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib SRCS = TARGET = example INTERFACE = example.i -MLFILE = example.ml -PROGFILE = example_prog.ml +PROGFILE = runme.ml OBJS = check: build @@ -16,23 +15,27 @@ build: static dynamic: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_dynamic static: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_static toplevel: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_static_toplevel clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' MLFILE='$(MLFILE)' ocaml_clean + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_clean diff --git a/Examples/ocaml/contract/example_prog.ml b/Examples/ocaml/contract/runme.ml similarity index 52% rename from Examples/ocaml/contract/example_prog.ml rename to Examples/ocaml/contract/runme.ml index 748109c2b..a77eed701 100644 --- a/Examples/ocaml/contract/example_prog.ml +++ b/Examples/ocaml/contract/runme.ml @@ -4,4 +4,9 @@ open Example let _ = print_endline "This won't throw." let _ = Printf.printf "Cos 1.0 is %f\n" (_cos '(1.0) as float) let _ = print_endline "This will throw." -let _ = Printf.printf "Cos 5.0 is %f\n" (_cos '(5.0) as float) +let _ = + try + Printf.printf "Cos 5.0 is %f\n" (_cos '(5.0) as float) + with Failure s -> + print_endline s ; + print_endline "Exception thrown." diff --git a/Examples/ocaml/scoped_enum/Makefile b/Examples/ocaml/scoped_enum/Makefile index 9655c98e6..cfed474ef 100644 --- a/Examples/ocaml/scoped_enum/Makefile +++ b/Examples/ocaml/scoped_enum/Makefile @@ -4,8 +4,7 @@ SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib SRCS = TARGET = example INTERFACE = example.i -MLFILE = example.ml -PROGFILE = example_prog.ml +PROGFILE = runme.ml OBJS = check: build @@ -16,23 +15,27 @@ build: static dynamic: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_dynamic_cpp static: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_static_cpp toplevel: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_static_cpp_toplevel clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' MLFILE='$(MLFILE)' ocaml_clean + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_clean diff --git a/Examples/ocaml/scoped_enum/example_prog.ml b/Examples/ocaml/scoped_enum/example_prog.ml deleted file mode 100644 index e19bb3454..000000000 --- a/Examples/ocaml/scoped_enum/example_prog.ml +++ /dev/null @@ -1,4 +0,0 @@ -open Swig -open Example - -let _ = _f (match Sys.argv.(1) with "Tag1" -> ``Tag1 | _ -> ``Tag2) diff --git a/Examples/ocaml/scoped_enum/runme.ml b/Examples/ocaml/scoped_enum/runme.ml new file mode 100644 index 000000000..f70b6e1f8 --- /dev/null +++ b/Examples/ocaml/scoped_enum/runme.ml @@ -0,0 +1,5 @@ +open Swig +open Example + +let arg = if Array.length Sys.argv > 1 then Sys.argv.(1) else "Tag1" +let _ = _f (match arg with "Tag1" -> ``Tag1 | _ -> ``Tag2) diff --git a/Examples/ocaml/shapes/Makefile b/Examples/ocaml/shapes/Makefile index b291d07e8..eab86d298 100644 --- a/Examples/ocaml/shapes/Makefile +++ b/Examples/ocaml/shapes/Makefile @@ -5,35 +5,38 @@ SWIGOPT = SRCS = example.c TARGET = example INTERFACE = example.i -MLFILE = example.ml -PROGFILE = example_prog.ml +PROGFILE = runme.ml OBJS = example.o check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_run -build: static static_top +build: static toplevel static: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - MLFILE='$(MLFILE)' PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ - ocaml_static_cpp - -static_top: + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - MLFILE='$(MLFILE)' PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ + PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ + ocaml_static_cpp + +toplevel: static + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_static_cpp_toplevel dynamic: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' - MLFILE='$(MLFILE)' PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ + PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_dynamic_cpp clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' MLFILE='$(MLFILE)' ocaml_clean + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_clean diff --git a/Examples/ocaml/shapes/example_prog.ml b/Examples/ocaml/shapes/runme.ml similarity index 98% rename from Examples/ocaml/shapes/example_prog.ml rename to Examples/ocaml/shapes/runme.ml index b9e35158a..a7a2f9374 100644 --- a/Examples/ocaml/shapes/example_prog.ml +++ b/Examples/ocaml/shapes/runme.ml @@ -1,4 +1,4 @@ -(* example_prog.ml *) +(* runme.ml *) open Swig ;; open Example ;; diff --git a/Examples/ocaml/simple/Makefile b/Examples/ocaml/simple/Makefile index 88fef7435..27fdb20f5 100644 --- a/Examples/ocaml/simple/Makefile +++ b/Examples/ocaml/simple/Makefile @@ -4,8 +4,7 @@ SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib SRCS = example.c TARGET = example INTERFACE = example.i -MLFILE = example.ml -PROGFILE = example_prog.ml +PROGFILE = runme.ml OBJS = example.o check: build @@ -16,23 +15,27 @@ build: static dynamic: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_dynamic static: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_static toplevel: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' MLFILE='$(MLFILE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ ocaml_static_toplevel clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' MLFILE='$(MLFILE)' ocaml_clean + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_clean diff --git a/Examples/ocaml/simple/index.html b/Examples/ocaml/simple/index.html index dace471a3..9ae997be5 100644 --- a/Examples/ocaml/simple/index.html +++ b/Examples/ocaml/simple/index.html @@ -1,18 +1,18 @@ -SWIG:Examples:python:simple +SWIG:Examples:ocaml:simple -SWIG/Examples/python/simple/ +SWIG/Examples/ocaml/simple/
            -

            Simple Python Example

            +

            Simple Ocaml Example

            -This example illustrates how you can hook Python to a very simple C program containing +This example illustrates how you can hook Ocaml to a very simple C program containing a function and a global variable.

            The C Code

            @@ -57,7 +57,7 @@ extern double Foo;

            Compilation

              -
            1. swig -python example.i +
            2. swig -ocaml example.i

            3. Compile example_wrap.c and example.c to create the extension examplemodule.so. @@ -65,29 +65,29 @@ to create the extension examplemodule.so.

              Using the extension

              -Click here to see a script that calls our C functions from Python. +Click here to see a script that calls our C functions from Ocaml.

              Key points

                -
              • Use the import statement to load your extension module from Python. For example: +
              • Use the open statement to load your extension module from Ocaml. For example:
                -import example
                +open Example
                 
                -
              • C functions work just like Python functions. For example: +
              • C functions work just like Ocaml functions. For example:
                -g = example.gcd(42,105)
                +let g = _gcd '(x,y) as int
                 
                -
              • C global variables are accessed through a special variable called 'cvar'. For example: +
              • C global variable Foo is wrapped as _Foo in ocaml. For example:
                -a = example.cvar.Foo
                +let _ = Printf.printf "Foo = %f\n" (_Foo '() as float)
                 
              diff --git a/Examples/ocaml/simple/example_prog.ml b/Examples/ocaml/simple/runme.ml similarity index 95% rename from Examples/ocaml/simple/example_prog.ml rename to Examples/ocaml/simple/runme.ml index cc3b973d8..4f7a407ef 100644 --- a/Examples/ocaml/simple/example_prog.ml +++ b/Examples/ocaml/simple/runme.ml @@ -1,4 +1,4 @@ -(* example_prog.ml *) +(* runme.ml *) open Swig open Example diff --git a/Examples/ocaml/std_string/Makefile b/Examples/ocaml/std_string/Makefile index 099b1fcee..655465692 100644 --- a/Examples/ocaml/std_string/Makefile +++ b/Examples/ocaml/std_string/Makefile @@ -12,6 +12,10 @@ check: build build: static static: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ diff --git a/Examples/ocaml/std_vector/Makefile b/Examples/ocaml/std_vector/Makefile index 099b1fcee..655465692 100644 --- a/Examples/ocaml/std_vector/Makefile +++ b/Examples/ocaml/std_vector/Makefile @@ -12,6 +12,10 @@ check: build build: static static: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ diff --git a/Examples/ocaml/std_vector/example.h b/Examples/ocaml/std_vector/example.h index b75359243..d968f6953 100644 --- a/Examples/ocaml/std_vector/example.h +++ b/Examples/ocaml/std_vector/example.h @@ -17,9 +17,8 @@ std::vector half(const std::vector& v) { } void halve_in_place(std::vector& v) { - // would you believe this is the same as the above? - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::vector::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } diff --git a/Examples/ocaml/std_vector/runme.ml b/Examples/ocaml/std_vector/runme.ml index feb70dd5e..0f5519b6f 100644 --- a/Examples/ocaml/std_vector/runme.ml +++ b/Examples/ocaml/std_vector/runme.ml @@ -14,7 +14,7 @@ let print_DoubleVector v = (fun v i -> print_float ((v '[i to int]) as float) ; print_string " ") ; - print_endline + print_endline "" end (* Call average with a Ocaml array... *) @@ -27,7 +27,7 @@ let rec fill_dv v x = fill_dv v (x *. x) end let _ = fill_dv v 0.999 -let _ = print_DoubleVector v ; print_endline "" +let _ = print_DoubleVector v let u = new_IntVector '() let _ = for i = 1 to 4 do u -> push_back ((i to int)) diff --git a/Examples/ocaml/stl/Makefile b/Examples/ocaml/stl/Makefile index 912dd9f8d..363311d95 100644 --- a/Examples/ocaml/stl/Makefile +++ b/Examples/ocaml/stl/Makefile @@ -15,19 +15,17 @@ static: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - ocaml_static_cpp - -director: + ocaml_core $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - ocaml_static_cpp_director + ocaml_static_cpp dynamic: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - ocaml_static_cpp + ocaml_dynamic_cpp toplevel: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ diff --git a/Examples/ocaml/stl/example.h b/Examples/ocaml/stl/example.h index df5762bfc..da1d50e22 100644 --- a/Examples/ocaml/stl/example.h +++ b/Examples/ocaml/stl/example.h @@ -8,7 +8,7 @@ using std::string; -double vec_write(std::vector v) { +void vec_write(std::vector v) { int n = 0; for( std::vector::iterator i = v.begin(); i != v.end(); diff --git a/Examples/ocaml/stl/example.i b/Examples/ocaml/stl/example.i index 19a80a605..214ac47a5 100644 --- a/Examples/ocaml/stl/example.i +++ b/Examples/ocaml/stl/example.i @@ -7,6 +7,4 @@ #define ENABLE_STRING_VECTOR %include stl.i -%feature("director"); - %include example.h diff --git a/Examples/ocaml/string_from_ptr/Makefile b/Examples/ocaml/string_from_ptr/Makefile index f9b027802..5ab5c44a9 100644 --- a/Examples/ocaml/string_from_ptr/Makefile +++ b/Examples/ocaml/string_from_ptr/Makefile @@ -1,39 +1,41 @@ TOP = ../.. SWIGEXE = $(TOP)/../swig SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib -SWIGOPT = -c++ SRCS = TARGET = example -INTERFACE = foolib.i -MLFILE = foolib.ml -PROGFILE = example_prog.ml +INTERFACE = example.i +PROGFILE = runme.ml OBJS = check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_run -build: static static_top +build: static toplevel static: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - MLFILE='$(MLFILE)' PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ - ocaml_static_cpp - -static_top: + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - MLFILE='$(MLFILE)' PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ - ocaml_static_cpp_toplevel + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ + ocaml_static + +toplevel: static + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ + ocaml_static_toplevel dynamic: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' - MLFILE='$(MLFILE)' PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ - ocaml_dynamic_cpp + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' + PROGFILE='$(PROGFILE)' OBJS='$(OBJS)' \ + ocaml_dynamic clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' MLFILE='$(MLFILE)' ocaml_clean + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_clean diff --git a/Examples/ocaml/string_from_ptr/foolib.i b/Examples/ocaml/string_from_ptr/example.i similarity index 94% rename from Examples/ocaml/string_from_ptr/foolib.i rename to Examples/ocaml/string_from_ptr/example.i index 86e0880eb..d66487940 100644 --- a/Examples/ocaml/string_from_ptr/foolib.i +++ b/Examples/ocaml/string_from_ptr/example.i @@ -1,4 +1,4 @@ -%module foolib +%module example %{ static int foo( char **buf ) { *buf = "string from c"; diff --git a/Examples/ocaml/string_from_ptr/example_prog.ml b/Examples/ocaml/string_from_ptr/runme.ml similarity index 88% rename from Examples/ocaml/string_from_ptr/example_prog.ml rename to Examples/ocaml/string_from_ptr/runme.ml index 8069dc228..039762017 100644 --- a/Examples/ocaml/string_from_ptr/example_prog.ml +++ b/Examples/ocaml/string_from_ptr/runme.ml @@ -1,7 +1,5 @@ -(* foo_program.ml -- the program using foolib *) - open Swig (* Give access to the swig library *) -open Foolib (* This is the name of your swig output *) +open Example (* This is the name of your swig output *) let results = _foo '() (* Function names are prefixed with _ in order to make them lex as identifiers in ocaml. Consider that diff --git a/Examples/ocaml/strings_test/Makefile b/Examples/ocaml/strings_test/Makefile index 24e2e6cca..38cf234da 100644 --- a/Examples/ocaml/strings_test/Makefile +++ b/Examples/ocaml/strings_test/Makefile @@ -9,9 +9,13 @@ PROGFILE = runme.ml check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' ocaml_run -build: static top +build: static toplevel static: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + ocaml_core $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ @@ -21,9 +25,9 @@ dynamic: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - ocaml_static_cpp + ocaml_dynamic_cpp -top: +toplevel: static $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ PROGFILE='$(PROGFILE)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ diff --git a/Examples/ocaml/strings_test/example.h b/Examples/ocaml/strings_test/example.h index 959404b5d..9dbc881a8 100644 --- a/Examples/ocaml/strings_test/example.h +++ b/Examples/ocaml/strings_test/example.h @@ -19,7 +19,7 @@ void takes_char_ptr( char *p ) { cout << "takes_char_ptr( \"" << p << "\" );" << endl; } -char *gives_char_ptr() { +const char *gives_const_char_ptr() { return "foo"; } @@ -28,8 +28,8 @@ void takes_and_gives_std_string( std::string &inout ) { inout.insert( inout.end(), ']' ); } -void takes_and_gives_char_ptr( char *&inout ) { - char *pout = strchr( inout, '.' ); +void takes_and_gives_const_char_ptr( const char *&inout ) { + const char *pout = strchr( inout, '.' ); if( pout ) inout = pout + 1; else inout = "foo"; } diff --git a/Examples/ocaml/strings_test/example.i b/Examples/ocaml/strings_test/example.i index be9eabfbc..d360715c1 100644 --- a/Examples/ocaml/strings_test/example.i +++ b/Examples/ocaml/strings_test/example.i @@ -11,4 +11,5 @@ using std::string; #include "example.h" %} +%include "std_string.i" %include example.h diff --git a/Examples/ocaml/strings_test/runme.ml b/Examples/ocaml/strings_test/runme.ml index 0eb56379c..727bc025e 100644 --- a/Examples/ocaml/strings_test/runme.ml +++ b/Examples/ocaml/strings_test/runme.ml @@ -8,10 +8,10 @@ let _ = print_endline ("_gives_std_string <<" ^ (get_string (_gives_std_string C_void)) ^ " >>") let _ = _takes_char_ptr (C_string "bar") let _ = print_endline - ("_gives_char_ptr << " ^ (get_string (_gives_char_ptr C_void)) ^ " >>") + ("_gives_const_char_ptr << " ^ (get_string (_gives_const_char_ptr C_void)) ^ " >>") let _ = print_endline ("_takes_and_gives_std_string << " ^ (get_string (_takes_and_gives_std_string (C_string "foo"))) ^ " >>") let _ = print_endline - ("_takes_and_gives_char_ptr << " ^ - (get_string (_takes_and_gives_char_ptr (C_string "bar.bar"))) ^ " >>") + ("_takes_and_gives_const_char_ptr << " ^ + (get_string (_takes_and_gives_const_char_ptr (C_string "bar.bar"))) ^ " >>") diff --git a/Examples/octave/callback/runme.m b/Examples/octave/callback/runme.m index 103985358..a9f2d98ed 100644 --- a/Examples/octave/callback/runme.m +++ b/Examples/octave/callback/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif # This file illustrates the cross language polymorphism using directors. diff --git a/Examples/octave/class/runme.m b/Examples/octave/class/runme.m index 04221b4bb..62b2db0ee 100644 --- a/Examples/octave/class/runme.m +++ b/Examples/octave/class/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif # This file illustrates the proxy class C++ interface generated # by SWIG. diff --git a/Examples/octave/constants/runme.m b/Examples/octave/constants/runme.m index c6ed24535..535280b6e 100644 --- a/Examples/octave/constants/runme.m +++ b/Examples/octave/constants/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif swigexample diff --git a/Examples/octave/contract/runme.m b/Examples/octave/contract/runme.m index fa36bbe10..f388e6105 100644 --- a/Examples/octave/contract/runme.m +++ b/Examples/octave/contract/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif swigexample diff --git a/Examples/octave/enum/runme.m b/Examples/octave/enum/runme.m index 0108135b2..f0c410103 100644 --- a/Examples/octave/enum/runme.m +++ b/Examples/octave/enum/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif swigexample diff --git a/Examples/octave/extend/runme.m b/Examples/octave/extend/runme.m index 4536f2761..c88a7c151 100644 --- a/Examples/octave/extend/runme.m +++ b/Examples/octave/extend/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif # This file illustrates the cross language polymorphism using directors. @@ -11,7 +14,7 @@ CEO=@(name) subclass(swigexample.Manager(name),'getPosition',@(self) "CEO"); # Create an instance of our employee extension class, CEO. The calls to # getName() and getPosition() are standard, the call to getTitle() uses -# the director wrappers to call CEO.getPosition. e = CEO("Alice") +# the director wrappers to call CEO.getPosition. e = CEO("Alice"); printf("%s is a %s\n",e.getName(),e.getPosition()); diff --git a/Examples/octave/funcptr/runme.m b/Examples/octave/funcptr/runme.m index 4e2e28fbc..670a0994b 100644 --- a/Examples/octave/funcptr/runme.m +++ b/Examples/octave/funcptr/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif swigexample diff --git a/Examples/octave/funcptr2/runme.m b/Examples/octave/funcptr2/runme.m index 574635ed2..3977b5b3c 100644 --- a/Examples/octave/funcptr2/runme.m +++ b/Examples/octave/funcptr2/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif swigexample diff --git a/Examples/octave/functor/runme.m b/Examples/octave/functor/runme.m index 8b41691c3..f5ab56d55 100644 --- a/Examples/octave/functor/runme.m +++ b/Examples/octave/functor/runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + # Operator overloading example swigexample diff --git a/Examples/octave/module_load/runme.m b/Examples/octave/module_load/runme.m index 30b7badb2..beab1213b 100644 --- a/Examples/octave/module_load/runme.m +++ b/Examples/octave/module_load/runme.m @@ -1,64 +1,77 @@ -# file: runme_args.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif # load module clear all; +assert(exist("swigexample") == 3); swigexample; +assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); -assert(exist("swigexample","var")); clear all +assert(exist("swigexample") == 3); swigexample; +assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); -assert(exist("swigexample","var")); clear all # load module in a function globally before base context clear all; -function testme +function testme_1 + assert(exist("swigexample") == 3); swigexample; + assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); - assert(exist("swigexample","var")); endfunction -testme -testme +testme_1 +testme_1 +assert(exist("swigexample") == 3); swigexample; +assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); -assert(exist("swigexample","var")); clear all -function testme +function testme_2 + assert(exist("swigexample") == 3); swigexample; + assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); - assert(exist("swigexample","var")); endfunction -testme -testme +testme_2 +testme_2 +assert(exist("swigexample") == 3); swigexample; +assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); -assert(exist("swigexample","var")); clear all # load module in a function globally after base context clear all; +assert(exist("swigexample") == 3); swigexample; +assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); -assert(exist("swigexample","var")); -function testme +function testme_3 + assert(exist("swigexample") == 3); swigexample; + assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); - assert(exist("swigexample","var")); endfunction -testme -testme +testme_3 +testme_3 clear all +assert(exist("swigexample") == 3); swigexample; +assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); -assert(exist("swigexample","var")); -function testme +function testme_4 + assert(exist("swigexample") == 3); swigexample; + assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); - assert(exist("swigexample","var")); endfunction -testme -testme +testme_4 +testme_4 clear all # octave 3.0.5 randomly crashes on the remaining tests @@ -68,13 +81,16 @@ endif # load module with no cvar clear all; +who; +assert(exist("swigexample2") == 3); swigexample2; +assert(isglobal("swigexample2")); assert(swigexample2.ivar == ifunc); -assert(exist("swigexample2","var")); -assert(!isglobal("cvar")) +assert(!exist("cvar", "var")); clear all +assert(exist("swigexample2") == 3); swigexample2; +assert(isglobal("swigexample2")); assert(swigexample2.ivar == ifunc); -assert(exist("swigexample2","var")); -assert(!isglobal("cvar")) +assert(!exist("cvar", "var")); clear all diff --git a/Examples/octave/operator/runme.m b/Examples/octave/operator/runme.m index 83197b410..e17494a84 100644 --- a/Examples/octave/operator/runme.m +++ b/Examples/octave/operator/runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + # Operator overloading example swigexample diff --git a/Examples/octave/pointer/runme.m b/Examples/octave/pointer/runme.m index a76de67de..1673915fe 100644 --- a/Examples/octave/pointer/runme.m +++ b/Examples/octave/pointer/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif swigexample; diff --git a/Examples/octave/reference/runme.m b/Examples/octave/reference/runme.m index 630ee0cd2..3f66d83d0 100644 --- a/Examples/octave/reference/runme.m +++ b/Examples/octave/reference/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif # This file illustrates the manipulation of C++ references in Octave diff --git a/Examples/octave/simple/runme.m b/Examples/octave/simple/runme.m index 6345df0cf..35365197c 100644 --- a/Examples/octave/simple/runme.m +++ b/Examples/octave/simple/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif swigexample diff --git a/Examples/octave/template/runme.m b/Examples/octave/template/runme.m index b0abbf22f..b7261b772 100644 --- a/Examples/octave/template/runme.m +++ b/Examples/octave/template/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif swigexample diff --git a/Examples/octave/variables/runme.m b/Examples/octave/variables/runme.m index c6788398b..df4cad77c 100644 --- a/Examples/octave/variables/runme.m +++ b/Examples/octave/variables/runme.m @@ -1,4 +1,7 @@ -# file: runme.m +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif swigexample @@ -48,7 +51,7 @@ swigexample.print_vars(); printf("\nNow I'm going to try and modify some read only variables\n"); -printf(" Tring to set 'path'\n"); +printf(" Trying to set 'path'\n"); try swigexample.cvar.path = "Whoa!"; printf("Hey, what's going on?!?! This shouldn't work\n"); diff --git a/Examples/perl5/check.list b/Examples/perl5/check.list index dda849311..78d45fc0b 100644 --- a/Examples/perl5/check.list +++ b/Examples/perl5/check.list @@ -6,7 +6,6 @@ constants2 extend funcptr import -java multimap multiple_inheritance pointer diff --git a/Examples/perl5/java/Example.java b/Examples/perl5/java/Example.java deleted file mode 100644 index 91ddb1ac5..000000000 --- a/Examples/perl5/java/Example.java +++ /dev/null @@ -1,29 +0,0 @@ -public class Example { - public int mPublicInt; - - public Example() { - mPublicInt = 0; - } - - public Example(int IntVal) { - mPublicInt = IntVal; - } - - - public int Add(int a, int b) { - return (a+b); - } - - public float Add(float a, float b) { - return (a+b); - } - - public String Add(String a, String b) { - return (a+b); - } - - public Example Add(Example a, Example b) { - return new Example(a.mPublicInt + b.mPublicInt); - } -} - diff --git a/Examples/perl5/java/Makefile b/Examples/perl5/java/Makefile deleted file mode 100644 index 7c133235f..000000000 --- a/Examples/perl5/java/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -TOP = ../.. -SWIGEXE = $(TOP)/../swig -SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib -CXXSRCS = -TARGET = example -INTERFACE = example.i -LIBS = -lm - -check: build - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' perl5_run - -build: Example.class Example.h - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - CXXSHARED="gcj -fpic -shared Example.class" PERL5_CCFLAGS='' PERL5_EXP='' LIBS="-lstdc++" perl5_cpp - -clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' perl5_clean - rm -f *.class Example.h - -Example.class Example.h: $(SRCDIR)Example.java - gcj -d . -fPIC -C -c -g $(SRCDIR)Example.java - gcjh Example.class diff --git a/Examples/perl5/java/example.i b/Examples/perl5/java/example.i deleted file mode 100644 index a82abb267..000000000 --- a/Examples/perl5/java/example.i +++ /dev/null @@ -1,10 +0,0 @@ -%module example - -%include - -%{ -#include "Example.h" -%} - - -%include Example.h diff --git a/Examples/perl5/java/runme.pl b/Examples/perl5/java/runme.pl deleted file mode 100644 index 56ad6e408..000000000 --- a/Examples/perl5/java/runme.pl +++ /dev/null @@ -1,29 +0,0 @@ -use example; - -example::JvCreateJavaVM(undef); -example::JvAttachCurrentThread(undef, undef); - -$e1 = new example::Example(1); -print $e1->{mPublicInt},"\n"; - -$e2 = new example::Example(2); -print $e2->{mPublicInt},"\n"; - -$i = $e1->Add(1,2); -print $i,"\n"; - -$d = $e2->Add(1.0,2.0); -print $d,"\n"; - -$d = $e2->Add("1","2"); -print $d,"\n"; - -$e3 = $e1->Add($e1,$e2); -print $e3->{mPublicInt},"\n"; - - -$s = $e2->Add("a","b"); -print $s,"\n"; - - -example::JvDetachCurrentThread() diff --git a/Examples/perl5/variables/runme.pl b/Examples/perl5/variables/runme.pl index 76e3dc8bc..2c3484db7 100644 --- a/Examples/perl5/variables/runme.pl +++ b/Examples/perl5/variables/runme.pl @@ -65,7 +65,7 @@ if (!$@) { } print " get error for 'status'\n"; -print " Tring to set 'path'\n"; +print " Trying to set 'path'\n"; eval { $example::path = "Whoa!";}; if (!$@) { die("path"); diff --git a/Examples/php/callback/Makefile b/Examples/php/callback/Makefile index cbc75774c..7f91fd56c 100644 --- a/Examples/php/callback/Makefile +++ b/Examples/php/callback/Makefile @@ -15,10 +15,5 @@ build: SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' php_cpp -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' $(SWIGLIB) CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' php_cpp_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/class/Makefile b/Examples/php/class/Makefile index 02a8668ac..063a0645f 100644 --- a/Examples/php/class/Makefile +++ b/Examples/php/class/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php_cpp -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_cpp_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/constants/Makefile b/Examples/php/constants/Makefile index 9dbd3842d..a05be202b 100644 --- a/Examples/php/constants/Makefile +++ b/Examples/php/constants/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/constants/runme.php b/Examples/php/constants/runme.php index cea06485f..91c597a40 100644 --- a/Examples/php/constants/runme.php +++ b/Examples/php/constants/runme.php @@ -12,16 +12,12 @@ print "EXPR = " . EXPR . " (should be 48.5484)\n"; print "iconst = " . iconst . " (should be 37)\n"; print "fconst = " . fconst . " (should be 3.14)\n"; -if (EXTERN!="EXTERN") { - print "EXTERN = " . EXTERN . " (Arg! This shouldn't print anything)\n"; -} else { - print "EXTERN defaults to 'EXTERN', it probably isn't defined (good)\n"; +$c = get_defined_constants(); +if (array_key_exists("EXTERN", $c)) { + print "EXTERN = " . $c["EXTERN"] . " (Arg! This shouldn't print anything)\n"; } - -if (FOO!="FOO") { - print "FOO = " . FOO . "(Arg! This shouldn't print anything)\n"; -} else { - print "FOO defaults to 'FOO', it probably isn't defined (good)\n"; +if (array_key_exists("FOO", $c)) { + print "FOO = " . $c["FOO"] . " (Arg! This shouldn't print anything)\n"; } diff --git a/Examples/php/cpointer/Makefile b/Examples/php/cpointer/Makefile index 05679f844..47e5ed9f9 100644 --- a/Examples/php/cpointer/Makefile +++ b/Examples/php/cpointer/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/disown/Makefile b/Examples/php/disown/Makefile index 02a8668ac..063a0645f 100644 --- a/Examples/php/disown/Makefile +++ b/Examples/php/disown/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php_cpp -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_cpp_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/disown/runme.php b/Examples/php/disown/runme.php index d90b03a9d..a70d7b061 100644 --- a/Examples/php/disown/runme.php +++ b/Examples/php/disown/runme.php @@ -26,7 +26,7 @@ $container->addShape($s); print "\nA total of " . Shape::nshapes() . " shapes were created\n"; # ----- Delete by the old references ----- -# This should not truely delete the shapes because they are now owned +# This should not truly delete the shapes because they are now owned # by the ShapeContainer. print "Delete the old references."; @@ -38,7 +38,7 @@ $s = NULL; print "\nA total of " . Shape::nshapes() . " shapes remain\n"; # ----- Delete by the container ----- -# This should truely delete the shapes +# This should truly delete the shapes print "Delete the container."; $container = NULL; diff --git a/Examples/php/enum/Makefile b/Examples/php/enum/Makefile index 95ebf8fc1..063a0645f 100644 --- a/Examples/php/enum/Makefile +++ b/Examples/php/enum/Makefile @@ -5,7 +5,7 @@ CXXSRCS = example.cxx TARGET = example INTERFACE = example.i LIBS = -SWIGOPT = -noproxy +SWIGOPT = check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php_cpp -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_cpp_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/enum/runme.php b/Examples/php/enum/runme.php index 55b0bc4c3..813476645 100644 --- a/Examples/php/enum/runme.php +++ b/Examples/php/enum/runme.php @@ -11,22 +11,22 @@ print " BLUE =" . BLUE; print " GREEN =" . GREEN; print "\n*** Foo::speed ***"; -print " Foo_IMPULSE =" . Foo_IMPULSE; -print " Foo_WARP =" . Foo_WARP; -print " Foo_LUDICROUS =" . Foo_LUDICROUS; +print " Foo::IMPULSE =" . Foo::IMPULSE; +print " Foo::WARP =" . Foo::WARP; +print " Foo::LUDICROUS =" . Foo::LUDICROUS; print "\nTesting use of enums with functions\n"; -enum_test(RED, Foo_IMPULSE); -enum_test(BLUE, Foo_WARP); -enum_test(GREEN, Foo_LUDICROUS); +enum_test(RED, Foo::IMPULSE); +enum_test(BLUE, Foo::WARP); +enum_test(GREEN, Foo::LUDICROUS); enum_test(1234,5678); print "\nTesting use of enum with class method\n"; -$f = new_Foo(); +$f = new Foo(); -Foo_enum_test($f,Foo_IMPULSE); -Foo_enum_test($f,Foo_WARP); -Foo_enum_test($f,Foo_LUDICROUS); +$f->enum_test(Foo::IMPULSE); +$f->enum_test(Foo::WARP); +$f->enum_test(Foo::LUDICROUS); ?> diff --git a/Examples/php/extend/Makefile b/Examples/php/extend/Makefile index cbc75774c..7f91fd56c 100644 --- a/Examples/php/extend/Makefile +++ b/Examples/php/extend/Makefile @@ -15,10 +15,5 @@ build: SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' php_cpp -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' $(SWIGLIB) CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' php_cpp_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/funcptr/Makefile b/Examples/php/funcptr/Makefile index 05679f844..47e5ed9f9 100644 --- a/Examples/php/funcptr/Makefile +++ b/Examples/php/funcptr/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/overloading/Makefile b/Examples/php/overloading/Makefile index 02a8668ac..063a0645f 100644 --- a/Examples/php/overloading/Makefile +++ b/Examples/php/overloading/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php_cpp -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_cpp_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/pointer/Makefile b/Examples/php/pointer/Makefile index 05679f844..47e5ed9f9 100644 --- a/Examples/php/pointer/Makefile +++ b/Examples/php/pointer/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/pragmas/Makefile b/Examples/php/pragmas/Makefile index 9dbd3842d..a05be202b 100644 --- a/Examples/php/pragmas/Makefile +++ b/Examples/php/pragmas/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/pragmas/example.i b/Examples/php/pragmas/example.i index c7e8bf303..ea9590b6f 100644 --- a/Examples/php/pragmas/example.i +++ b/Examples/php/pragmas/example.i @@ -25,7 +25,8 @@ %pragma(php) code=" # This code is inserted into example.php -echo \"this was php code\\n\"; +echo \"This was php code\\n\"; " +%pragma(php) version="1.5" %pragma(php) phpinfo="php_info_print_table_start();" diff --git a/Examples/php/pragmas/include.php b/Examples/php/pragmas/include.php index e19880a06..11d985d66 100644 --- a/Examples/php/pragmas/include.php +++ b/Examples/php/pragmas/include.php @@ -1,7 +1,7 @@ diff --git a/Examples/php/pragmas/runme.php b/Examples/php/pragmas/runme.php index 538548b6f..7b2c179cb 100644 --- a/Examples/php/pragmas/runme.php +++ b/Examples/php/pragmas/runme.php @@ -1,5 +1,9 @@ getVersion()) . "\n"; ?> diff --git a/Examples/php/proxy/Makefile b/Examples/php/proxy/Makefile index 02a8668ac..063a0645f 100644 --- a/Examples/php/proxy/Makefile +++ b/Examples/php/proxy/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php_cpp -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_cpp_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/reference/Makefile b/Examples/php/reference/Makefile index 02a8668ac..063a0645f 100644 --- a/Examples/php/reference/Makefile +++ b/Examples/php/reference/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php_cpp -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_cpp_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/simple/Makefile b/Examples/php/simple/Makefile index 05679f844..47e5ed9f9 100644 --- a/Examples/php/simple/Makefile +++ b/Examples/php/simple/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/sync/Makefile b/Examples/php/sync/Makefile index 02a8668ac..063a0645f 100644 --- a/Examples/php/sync/Makefile +++ b/Examples/php/sync/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php_cpp -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_cpp_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/value/Makefile b/Examples/php/value/Makefile index 674e4368e..47e5ed9f9 100644 --- a/Examples/php/value/Makefile +++ b/Examples/php/value/Makefile @@ -5,7 +5,7 @@ SRCS = example.c TARGET = example INTERFACE = example.i LIBS = -SWIGOPT = -noproxy +SWIGOPT = check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/value/runme.php b/Examples/php/value/runme.php index 49115376c..569c87cf5 100644 --- a/Examples/php/value/runme.php +++ b/Examples/php/value/runme.php @@ -3,15 +3,15 @@ require "example.php"; - $v = new_vector(); - vector_x_set($v,1.0); - vector_y_set($v,2.0); - vector_z_set($v,3.0); + $v = new Vector(); + $v->x = 1.0; + $v->y = 2.0; + $v->z = 3.0; - $w = new_vector(); - vector_x_set($w,10.0); - vector_y_set($w,11.0); - vector_z_set($w,12.0); + $w = new Vector(); + $w->x = 10.0; + $w->y = 11.0; + $w->z = 12.0; echo "I just created the following vector\n"; vector_print($v); @@ -25,7 +25,7 @@ echo "\nNow I'm going to add the vectors together\n"; - $r = new_vector(); + $r = new Vector(); vector_add($v, $w, $r); vector_print($r); diff --git a/Examples/php/variables/Makefile b/Examples/php/variables/Makefile index 05679f844..47e5ed9f9 100644 --- a/Examples/php/variables/Makefile +++ b/Examples/php/variables/Makefile @@ -16,11 +16,5 @@ build: SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ php -static: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' \ - php_static - clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php/variables/runme.php b/Examples/php/variables/runme.php index bbfeb610b..14f27f389 100644 --- a/Examples/php/variables/runme.php +++ b/Examples/php/variables/runme.php @@ -26,10 +26,10 @@ echo "pt = ".pt_get(), point_print(pt_get()) , "\n"; /* Try to set the values of some global variables */ -$a = "42.14"; + $a = "42.14"; ivar_set($a); -echo "a = $a\n"; + echo "a = $a\n"; svar_set(-31000); lvar_set(65537); uivar_set(123456); diff --git a/Examples/python/check.list b/Examples/python/check.list index a43a5fca0..0798b5f7e 100644 --- a/Examples/python/check.list +++ b/Examples/python/check.list @@ -4,6 +4,7 @@ class constants contract docstrings +doxygen enum exception exceptproxy @@ -14,7 +15,6 @@ functor import import_template import_packages -java #libffi multimap operator diff --git a/Examples/python/class/index.html b/Examples/python/class/index.html index 2e1baa395..755c11470 100644 --- a/Examples/python/class/index.html +++ b/Examples/python/class/index.html @@ -86,7 +86,7 @@ Note: when creating a C++ extension, you must run SWIG with the -c++ op

              A sample Python script

              -Click here to see a script that calls the C++ functions from Python. +Click here to see a script that calls the C++ functions from Python.

              Key points

              diff --git a/Examples/python/constants/index.html b/Examples/python/constants/index.html index 35cc0d7e6..6f9e2018b 100644 --- a/Examples/python/constants/index.html +++ b/Examples/python/constants/index.html @@ -17,7 +17,7 @@ to see a SWIG interface with some constant declarations in it.

              Accessing Constants from Python

              -Click here to see a script that prints out the values +Click here to see a script that prints out the values of the constants contained in the above file.

              Key points

              diff --git a/Examples/python/doxygen/Makefile b/Examples/python/doxygen/Makefile new file mode 100644 index 000000000..1a0e3d7c5 --- /dev/null +++ b/Examples/python/doxygen/Makefile @@ -0,0 +1,27 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = -doxygen + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' python_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' python_cpp + +static: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' \ + TARGET='mypython' INTERFACE='$(INTERFACE)' python_cpp_static + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='$(TARGET)' python_clean + rm -f example.html diff --git a/Examples/python/doxygen/example.cxx b/Examples/python/doxygen/example.cxx new file mode 100644 index 000000000..ccdb87dfe --- /dev/null +++ b/Examples/python/doxygen/example.cxx @@ -0,0 +1,48 @@ +/* File : example.cxx */ + +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +Circle::Circle(double r) : radius(r) { + NumCircles++; +} + +double Circle::area() { + return M_PI*radius*radius; +} + +double Circle::perimeter() { + return 2*M_PI*radius; +} + +Square::Square(double w) : width(w) { + NumSquares++; +} + +double Square::area() { + return width*width; +} + +double Square::perimeter() { + return 4*width; +} + +int NumSquares = 0; +int NumCircles = 0; + +Square MakeSquare(double r) { + return Square(r); +} + +Circle MakeCircle(double w) { + return Circle(w); +} + diff --git a/Examples/python/doxygen/example.dsp b/Examples/python/doxygen/example.dsp new file mode 100644 index 000000000..95ad8f173 --- /dev/null +++ b/Examples/python/doxygen/example.dsp @@ -0,0 +1,152 @@ +# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=example - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "example.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "example - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "example - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "example - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "$(PYTHON_INCLUDE)" /D "SWIG_PYTHON_INTERPRETER_NO_DEBUG" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib "$(PYTHON_LIB)" /nologo /dll /debug /machine:I386 /out:"_example.pyd" /pdbtype:sept + +!ELSEIF "$(CFG)" == "example - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "$(PYTHON_INCLUDE)" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib "$(PYTHON_LIB)" /nologo /dll /machine:I386 /out:"_example.pyd" + +!ENDIF + +# Begin Target + +# Name "example - Win32 Debug" +# Name "example - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\example.cxx +# End Source File +# Begin Source File + +SOURCE=.\example_wrap.cxx +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\example.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=.\example.i + +!IF "$(CFG)" == "example - Win32 Debug" + +# Begin Custom Build +InputPath=.\example.i +InputName=example + +"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + echo In order to function correctly, please ensure the following environment variables are correctly set: + echo PYTHON_INCLUDE: %PYTHON_INCLUDE% + echo PYTHON_LIB: %PYTHON_LIB% + echo on + ..\..\..\swig.exe -c++ -python "$(InputPath)" + +# End Custom Build + +!ELSEIF "$(CFG)" == "example - Win32 Release" + +# Begin Custom Build +InputPath=.\example.i +InputName=example + +"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + echo In order to function correctly, please ensure the following environment variables are correctly set: + echo PYTHON_INCLUDE: %PYTHON_INCLUDE% + echo PYTHON_LIB: %PYTHON_LIB% + echo on + ..\..\..\swig.exe -c++ -python "$(InputPath)" + +# End Custom Build + +!ENDIF + +# End Source File +# End Target +# End Project diff --git a/Examples/python/doxygen/example.h b/Examples/python/doxygen/example.h new file mode 100644 index 000000000..203348ae4 --- /dev/null +++ b/Examples/python/doxygen/example.h @@ -0,0 +1,107 @@ +/*! \file example.h +This file provides a simple set of Shape classes. */ + +/*! Base class for all shapes. + \author Bob + */ +class Shape { +public: + /*! Default constructor for creating a Shape */ + Shape() { + nshapes++; + } + /*! Destructor for destroying a Shape */ + virtual ~Shape() { + nshapes--; + } + double x; /*!< x co-ordinate */ + double y; /*!< y co-ordinate */ + void move(double dx, double dy); /*!< Move a shape to a new co-ordinate + \param dx x co-ordinate + \param dy y co-ordinate */ + virtual double area() = 0; /*!< \return the area */ + virtual double perimeter() = 0; /*!< \return the perimeter */ + static int nshapes; /*!< Number of shapes currently in existence */ +}; + +/*! A class for representing a circle. + \author Jack + */ +class Circle : public Shape { +private: + double radius; +public: + /*! Construct a circle + * \param r radius of the circle */ + Circle(double r); + /*! Calculate the area of the circle + * \return calculated area */ + virtual double area(); + /*! Calculate the perimeter of the circle + * \return calculated perimeter of the circle */ + virtual double perimeter(); +}; + +/// A class for representing a square. +class Square : public Shape { +private: + double width; +public: + /** Construct a square + * \param w width of the square */ + Square(double w); + /** Calculate the area of the square + * \return calculated area */ + virtual double area(); + /** Calculate the perimeter of the square + * \return calculated perimeter of the square */ + virtual double perimeter(); +}; + +/// A class for representing a rectangle, templated on the type for the rectangle dimensions +template +class Rectangle : public Shape { +private: + T height; + T width; +public: + /** Construct a rectangle + * \param h height of the rectangle + * \param w width of the rectangle */ + Rectangle(T h, T w) : height(h), width(w) {} + /** Calculate the area of the rectangle + * \return calculated area */ + virtual double area() { return width*height; } + /** Calculate the perimeter of the rectangle + * \return calculated perimeter of the rectangle */ + virtual double perimeter() { return 2*height + 2*width; } +}; + + +/*! Factory function for creating a square + * \param r width of the square + * \return a fully constructed square */ +Square MakeSquare(double r); + +/*! Factory function for creating a circle + * \param w radius of the circle + * \return a fully constructed circle */ +Circle MakeCircle(double w); + +/*! Factory function for creating a rectangle + * \param h height of the rectangle + * \param w width of the rectangle + * \return a fully constructed rectangle */ +template +Rectangle MakeRectangle(T h, T w) { + return Rectangle(h, w); +} + + + +/*! Total number of circles ever created */ +extern int NumCircles; + +/// Total number of squares ever created +extern int NumSquares; + diff --git a/Examples/python/doxygen/example.i b/Examples/python/doxygen/example.i new file mode 100644 index 000000000..803563dd9 --- /dev/null +++ b/Examples/python/doxygen/example.i @@ -0,0 +1,17 @@ +%module example + +%{ +#include "example.h" +%} + +%immutable NumSquares; +%immutable NumCircles; + +%include "example.h" + +/*! - this instantiation uses type int */ +%template(RectangleInt) Rectangle; + +/*! - this instantiation uses type int */ +%template(MakeRectangleInt) MakeRectangle; + diff --git a/Examples/python/doxygen/runme.py b/Examples/python/doxygen/runme.py new file mode 100644 index 000000000..e23528874 --- /dev/null +++ b/Examples/python/doxygen/runme.py @@ -0,0 +1,28 @@ +# This example shows simple usage of the wrapped Shape classes. +# The main purpose of this example is to show the doxygen comments translation to PyDoc comments. +# Users should look at the generated example.py file. +# The generated PyDoc can be viewed in a browser by opening the example.html file. + +import example + +print "Creating some objects:" +c = example.MakeCircle(10) +print " Created circle", c +s = example.MakeSquare(10) +print " Created square", s +r = example.MakeRectangleInt(10, 20) +print " Created rectangle", r + +print "\nHere are some properties of the shapes:" +for o in [c, s, r]: + print " ", o + print " area = ", o.area() + print " perimeter = ", o.perimeter() + +print "\nRunning pydoc, this is the equivalent to executing: pydoc -w ./example.py" + +import pydoc + +pydoc.writedoc("example") + +print "Open example.html in your browser to view the generated python docs" diff --git a/Examples/python/enum/index.html b/Examples/python/enum/index.html index 776030ffa..2f7c42095 100644 --- a/Examples/python/enum/index.html +++ b/Examples/python/enum/index.html @@ -19,7 +19,7 @@ of enumerated types are handled as integers.

              Notes

              diff --git a/Examples/python/exception/example.h b/Examples/python/exception/example.h index 8f9a977b0..bc744cda7 100644 --- a/Examples/python/exception/example.h +++ b/Examples/python/exception/example.h @@ -1,6 +1,6 @@ /* File : example.h */ -#include +#include #ifndef SWIG struct A { }; @@ -16,30 +16,26 @@ public: char msg[256]; }; -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - class Test { public: - int simple() throw(int) { + int simple() { throw(37); return 1; } - int message() throw(const char *) { + int message() { throw("I died."); return 1; } - int hosed() throw(Exc) { + int hosed() { throw(Exc(42,"Hosed")); return 1; } - int unknown() throw(A*) { + int unknown() { static A a; throw &a; return 1; } - int multi(int x) throw(int, const char *, Exc) { + int multi(int x) { if (x == 1) throw(37); if (x == 2) throw("Bleah!"); if (x == 3) throw(Exc(42,"No-go-diggy-die")); @@ -47,7 +43,3 @@ public: } }; -#if defined(_MSC_VER) - #pragma warning(default: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - diff --git a/Examples/python/exception/example.i b/Examples/python/exception/example.i index 817c5221c..3a3a6548f 100644 --- a/Examples/python/exception/example.i +++ b/Examples/python/exception/example.i @@ -7,6 +7,12 @@ %include "std_string.i" +%catches(int) Test::simple(); +%catches(const char *) Test::message(); +%catches(Exc) Test::hosed(); +%catches(A*) Test::unknown(); +%catches(int, const char *, Exc) Test::multi(int x); + /* Let's just grab the original header file here */ %include "example.h" diff --git a/Examples/python/exceptproxy/example.h b/Examples/python/exceptproxy/example.h index ec7107a5e..3ee6d765d 100644 --- a/Examples/python/exceptproxy/example.h +++ b/Examples/python/exceptproxy/example.h @@ -8,10 +8,6 @@ class FullError { FullError(int m) : maxsize(m) { } }; -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - template class Queue { int maxsize; T *items; @@ -27,7 +23,7 @@ template class Queue { ~Queue() { delete [] items; } - void enqueue(T x) throw(FullError) { + void enqueue(T x) { if (nitems == maxsize) { throw FullError(maxsize); } @@ -47,8 +43,3 @@ template class Queue { } }; - -#if defined(_MSC_VER) - #pragma warning(default: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - diff --git a/Examples/python/exceptproxy/example.i b/Examples/python/exceptproxy/example.i index 0a46afbb6..4ad960845 100644 --- a/Examples/python/exceptproxy/example.i +++ b/Examples/python/exceptproxy/example.i @@ -20,29 +20,12 @@ the header file, the enqueue method throws FullError and the dequeue method throws EmptyError. Since we don't want to define an exception handler for everything, we - simply write a handler each method individually. + simply write a handler for each method individually. Note: the *::enqueue syntax means that we simply define the handler for any class with this method defined. */ -/* - First we need to 'disable' the default swig throw mechanism for the - FullError class. We do this by rethrowing the exception. - - Note that this is necessary since the class appears in a throw - declaration: - - - void enqueue(T x) throw(FullError); - - hence, swig recognizes it as an exception class and it will generate - the necessary code to catch it and rethrow it to the python side. - -*/ -%typemap(throws) FullError "(void)$1; throw;"; - - %exception *::enqueue { try { $action @@ -76,15 +59,15 @@ */ /* - Now, the EmpytError doesn't appear in a throw declaration, and hence - we need to 'mark' it as an exception class. In python, classes that - are used as exception are 'special', and need to be wrapped as - 'classic' ones. - - This is a python issue, and if you don't mark the class, you will - see 'interesting' behaviours at the python side. - + Python classes that are used as exceptions need to be subclasses of the + "Exception" class, and so SWIG needs to know which wrapped classes may be + used in this way. You can explicitly tell SWIG this by using + %exceptionclass. SWIG will implicitly set this feature for classes which + appear in a throw declaration, but it's not a problem to explicitly + mark such classes as well. + This is a Python requirement - if you fail to mark such classes with + %exceptionclass you may see 'interesting' behaviour on the Python side. */ %exceptionclass EmptyError; %exceptionclass FullError; diff --git a/Examples/python/extend/runme.py b/Examples/python/extend/runme.py index 2bb38fadc..e97358b99 100644 --- a/Examples/python/extend/runme.py +++ b/Examples/python/extend/runme.py @@ -18,7 +18,7 @@ class CEO(example.Manager): # Create an instance of our employee extension class, CEO. The calls to # getName() and getPosition() are standard, the call to getTitle() uses -# the director wrappers to call CEO.getPosition. e = CEO("Alice") +# the director wrappers to call CEO.getPosition. e = CEO("Alice") print e.getName(), "is a", e.getPosition() diff --git a/Examples/python/funcptr/index.html b/Examples/python/funcptr/index.html index e41e0db45..58790276e 100644 --- a/Examples/python/funcptr/index.html +++ b/Examples/python/funcptr/index.html @@ -65,7 +65,7 @@ Here are some files that illustrate this with a simple example:
            4. example.c
            5. example.h
            6. example.i (SWIG interface) -
            7. example.py (Sample script) +
            8. runme.py (Sample script)

          Notes

          diff --git a/Examples/python/import_packages/Makefile b/Examples/python/import_packages/Makefile index f428d6f5c..c7f9a830b 100644 --- a/Examples/python/import_packages/Makefile +++ b/Examples/python/import_packages/Makefile @@ -8,11 +8,12 @@ import_packages_subdirs = \ from_init1 \ from_init2 \ from_init3 \ + module_is_init \ relativeimport1 \ relativeimport2 \ relativeimport3 \ split_modules \ - namespace_pkg + namespace_pkg \ check: build @@ -21,19 +22,19 @@ check: build mkdir -p `dirname $$file`; \ cp "${SRCDIR}$$file" "$$file" || exit 1; \ done; \ - fi; \ + fi for s in $(import_packages_subdirs); do \ - (cd $$s && $(MAKE) check); \ + (cd $$s && $(MAKE) check) || exit 1; \ done build: for s in $(import_packages_subdirs); do \ - (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' build); \ + (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' build) || exit 1; \ done static: for s in $(import_packages_subdirs); do \ - (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' static); \ + (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' static) || exit 1; \ done clean: @@ -42,7 +43,7 @@ clean: for file in `cd $(SRCDIR) && find . -type f -name "*.py"`; do \ rm -f "$$file" || exit 1; \ done; \ - fi; \ + fi for s in $(import_packages_subdirs); do \ - (cd $$s && $(MAKE) clean); \ + (cd $$s && $(MAKE) clean) || exit 1; \ done diff --git a/Examples/python/import_packages/from_init1/runme.py b/Examples/python/import_packages/from_init1/runme.py index dda397487..a663a136b 100644 --- a/Examples/python/import_packages/from_init1/runme.py +++ b/Examples/python/import_packages/from_init1/runme.py @@ -1,13 +1,35 @@ -import sys import os.path +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) # Test import of modules content from within __init__.py testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) + python 'import' in __init__.py" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2 print " Finished importing py2.pkg2" + commandline = sys.executable + " -m py2.pkg2.bar" + run_except_on_windows(commandline) + commandline = sys.executable + " -m py2.pkg2.foo" + run_except_on_windows(commandline) else: import py3.pkg2 print " Finished importing py3.pkg2" + # commandline = sys.executable + " -m py3.pkg2.bar" + # run_except_on_windows(commandline) + # commandline = sys.executable + " -m py3.pkg2.foo" + # run_except_on_windows(commandline) + +# TODO: Commented out code above results in (from python-3.6 onwards): +# RuntimeWarning: 'py3.pkg2.bar' found in sys.modules after import of package 'py3.pkg2', but prior to execution of 'py3.pkg2.bar'; this may result in unpredictable behaviour diff --git a/Examples/python/import_packages/from_init2/runme.py b/Examples/python/import_packages/from_init2/runme.py index dda397487..3c7b12693 100644 --- a/Examples/python/import_packages/from_init2/runme.py +++ b/Examples/python/import_packages/from_init2/runme.py @@ -1,13 +1,31 @@ -import sys import os.path +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) # Test import of modules content from within __init__.py testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) + python 'import' in __init__.py" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2 print " Finished importing py2.pkg2" + commandline = sys.executable + " -m py2.pkg2.bar" + run_except_on_windows(commandline) else: import py3.pkg2 print " Finished importing py3.pkg2" + # commandline = sys.executable + " -m py3.pkg2.bar" + # run_except_on_windows(commandline) + +# TODO: Commented out code above results in (from python-3.6 onwards): +# RuntimeWarning: 'py3.pkg2.bar' found in sys.modules after import of package 'py3.pkg2', but prior to execution of 'py3.pkg2.bar'; this may result in unpredictable behaviour diff --git a/Examples/python/import_packages/from_init3/runme.py b/Examples/python/import_packages/from_init3/runme.py index dda397487..3c7b12693 100644 --- a/Examples/python/import_packages/from_init3/runme.py +++ b/Examples/python/import_packages/from_init3/runme.py @@ -1,13 +1,31 @@ -import sys import os.path +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) # Test import of modules content from within __init__.py testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) + python 'import' in __init__.py" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2 print " Finished importing py2.pkg2" + commandline = sys.executable + " -m py2.pkg2.bar" + run_except_on_windows(commandline) else: import py3.pkg2 print " Finished importing py3.pkg2" + # commandline = sys.executable + " -m py3.pkg2.bar" + # run_except_on_windows(commandline) + +# TODO: Commented out code above results in (from python-3.6 onwards): +# RuntimeWarning: 'py3.pkg2.bar' found in sys.modules after import of package 'py3.pkg2', but prior to execution of 'py3.pkg2.bar'; this may result in unpredictable behaviour diff --git a/Examples/python/import_packages/module_is_init/Makefile b/Examples/python/import_packages/module_is_init/Makefile new file mode 100644 index 000000000..43763aa4b --- /dev/null +++ b/Examples/python/import_packages/module_is_init/Makefile @@ -0,0 +1,15 @@ +TOP = ../../.. +LIBS = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' python_run + +build: + cd pkg1 && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' build + +static: + cd pkg1 && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' static + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' python_clean + cd pkg1 && $(MAKE) clean diff --git a/Examples/python/import_packages/module_is_init/README b/Examples/python/import_packages/module_is_init/README new file mode 100644 index 000000000..ee7391cda --- /dev/null +++ b/Examples/python/import_packages/module_is_init/README @@ -0,0 +1,18 @@ +This example tests renaming the generated SWIG pure Python module to __init__.py +to turn the module into a Python package. + +Use 'python runme.py' to run the test. + +Overview: +--------- + +SWIG generates a pure Python module foo.py from the input interface file foo.i. +The foo.py file is generated within the pkg1 directory and is then renamed __init__.py. +This results in everything in the SWIG generated module being available in the Python +pkg1 package. + +This approach of turning the SWIG generated module into a package worked in versions +of SWIG up to swig-3.0.8, but stopped working from swig-3.0.9 until it was +re-instated in swig-4.0.0. However, Python 2.7 or 3.3 and later are needed to +work out of the box. Python 3.2 does not work as this version of Python does +not set __package__ in __init__.py. diff --git a/Examples/python/import_packages/module_is_init/pkg1/Makefile b/Examples/python/import_packages/module_is_init/pkg1/Makefile new file mode 100644 index 000000000..d9d83ed0a --- /dev/null +++ b/Examples/python/import_packages/module_is_init/pkg1/Makefile @@ -0,0 +1,20 @@ +TOP = ../../../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SWIGOPT = +LIBS = + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' TARGET='foo' INTERFACE='foo.i' python_cpp + mv foo.py __init__.py + +static: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' TARGET='foo' INTERFACE='foo.i' python_cpp_static + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='foo' python_clean + rm -f __init__.py diff --git a/Examples/python/import_packages/module_is_init/pkg1/foo.hpp b/Examples/python/import_packages/module_is_init/pkg1/foo.hpp new file mode 100644 index 000000000..01c462266 --- /dev/null +++ b/Examples/python/import_packages/module_is_init/pkg1/foo.hpp @@ -0,0 +1,10 @@ + +int foofunction(int i) { + return i *= 10; +} + +struct FooClass { + int foomethod(int i) { + return i += 5; + } +}; diff --git a/Examples/python/import_packages/module_is_init/pkg1/foo.i b/Examples/python/import_packages/module_is_init/pkg1/foo.i new file mode 100644 index 000000000..f8d71380c --- /dev/null +++ b/Examples/python/import_packages/module_is_init/pkg1/foo.i @@ -0,0 +1,5 @@ +%module foo +%{ +#include "./foo.hpp" +%} +%include "./foo.hpp" diff --git a/Examples/python/import_packages/module_is_init/runme.py b/Examples/python/import_packages/module_is_init/runme.py new file mode 100644 index 000000000..b5e646e85 --- /dev/null +++ b/Examples/python/import_packages/module_is_init/runme.py @@ -0,0 +1,26 @@ +import os.path +import sys + +# Test import of a SWIG generated module renamed as the package's __init__.py +testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) +print "Testing " + testname + " - module renamed as __init__.py" + +if sys.version_info >= (3, 0, 0) and sys.version_info < (3, 3, 0): + print " Not importing as Python version is >= 3.0 and < 3.3" + # Package detection does not work in these versions. + # Can be fixed by using this in the interface file: + # %module(moduleimport="from . import $module") foo # without -builtin + # %module(moduleimport="from .$module import *") foo # with -builtin + sys.exit(0) + +import pkg1 +print " Finished importing pkg1" + +if pkg1.foofunction(123) != 1230: + raise RuntimeError("foofunction failed") + +fc = pkg1.FooClass() +if fc.foomethod(1) != 6: + raise RuntimeError("foomethod failed") + +print " Finished testing pkg1" diff --git a/Examples/python/import_packages/namespace_pkg/nonpkg.py b/Examples/python/import_packages/namespace_pkg/nonpkg.py index acf0aedbd..52be74db4 100644 --- a/Examples/python/import_packages/namespace_pkg/nonpkg.py +++ b/Examples/python/import_packages/namespace_pkg/nonpkg.py @@ -1,5 +1,22 @@ +import os +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) + +print(" Starting subtest " + os.path.basename(__file__)) + # import robin as a module in the global namespace import robin +print(" Finished importing robin") -assert(robin.run() == "AWAY!") +if not(robin.run() == "AWAY!"): + raise RuntimeError("test failed") + +commandline = sys.executable + " -m robin" +run_except_on_windows(commandline) diff --git a/Examples/python/import_packages/namespace_pkg/normal.py b/Examples/python/import_packages/namespace_pkg/normal.py index fc26c0216..0eb8f517c 100644 --- a/Examples/python/import_packages/namespace_pkg/normal.py +++ b/Examples/python/import_packages/namespace_pkg/normal.py @@ -1,7 +1,23 @@ +import os +import subprocess import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) + +print(" Starting subtest " + os.path.basename(__file__)) + # Package brave found under one path -sys.path.insert(0, 'path1') +sys.path.insert(0, "path1") from brave import robin +print(" Finished from brave import robin") -assert(robin.run() == "AWAY!") +if not(robin.run() == "AWAY!"): + raise RuntimeError("test failed") + +commandline = sys.executable + " -m brave.robin" +run_except_on_windows(commandline, env = {"PYTHONPATH": "path1"}) diff --git a/Examples/python/import_packages/namespace_pkg/nstest.py b/Examples/python/import_packages/namespace_pkg/nstest.py index 9b075ad8c..4d618a6ad 100644 --- a/Examples/python/import_packages/namespace_pkg/nstest.py +++ b/Examples/python/import_packages/namespace_pkg/nstest.py @@ -1,11 +1,17 @@ import sys import os import shutil +import subprocess import zipfile +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) def copyMods(): - dirs = ['path1', 'path2', 'path3'] + dirs = ["path1", "path2", "path3"] # Clean out any old package paths for d in dirs: @@ -14,20 +20,20 @@ def copyMods(): for d in dirs: os.mkdir(d) - os.mkdir(os.path.join(d, 'brave')) + os.mkdir(os.path.join(d, "brave")) - shutil.copy('robin.py', os.path.join('path1', 'brave')) - os.system('cp _robin.* ' + os.path.join('path1', 'brave')) + shutil.copy("robin.py", os.path.join("path1", "brave")) + subprocess.check_call("cp _robin.* " + os.path.join("path1", "brave"), shell=True) - shutil.copy('robin.py', os.path.join('path2', 'brave')) - os.system('cp _robin.* ' + os.path.join('path3', 'brave')) + shutil.copy("robin.py", os.path.join("path2", "brave")) + subprocess.check_call("cp _robin.* " + os.path.join("path3", "brave"), shell=True) mkzip() def mkzip(): zf = zipfile.ZipFile("path4.zip", "w") - zf.writestr("brave/", b'') - zf.write('robin.py', 'brave/robin.py') + zf.writestr("brave/", b"") + zf.write("robin.py", "brave/robin.py") zf.close() @@ -35,10 +41,10 @@ def main(): copyMods() # Run each test with a separate interpreter - os.system(sys.executable + " nonpkg.py") - os.system(sys.executable + " normal.py") - os.system(sys.executable + " split.py") - os.system(sys.executable + " zipsplit.py") + run_except_on_windows(sys.executable + " nonpkg.py") + run_except_on_windows(sys.executable + " normal.py") + run_except_on_windows(sys.executable + " split.py") + run_except_on_windows(sys.executable + " zipsplit.py") if __name__ == "__main__": diff --git a/Examples/python/import_packages/namespace_pkg/runme.py b/Examples/python/import_packages/namespace_pkg/runme.py index 9c22d36fb..d2af05619 100644 --- a/Examples/python/import_packages/namespace_pkg/runme.py +++ b/Examples/python/import_packages/namespace_pkg/runme.py @@ -1,7 +1,8 @@ # These examples rely on namespace packages. Don't # run them for old python interpreters. -import sys import os.path +import subprocess +import sys testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - namespace packages" diff --git a/Examples/python/import_packages/namespace_pkg/split.py b/Examples/python/import_packages/namespace_pkg/split.py index 1b66c2d49..9d786dc07 100644 --- a/Examples/python/import_packages/namespace_pkg/split.py +++ b/Examples/python/import_packages/namespace_pkg/split.py @@ -1,9 +1,25 @@ +import os +import subprocess import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) + +print(" Starting subtest " + os.path.basename(__file__)) + # Package brave split into two paths. # path2/brave/robin.py and path3/brave/_robin.so -sys.path.insert(0, 'path2') -sys.path.insert(0, 'path3') +sys.path.insert(0, "path2") +sys.path.insert(0, "path3") from brave import robin +print(" Finished from brave import robin") -assert(robin.run() == "AWAY!") +if not(robin.run() == "AWAY!"): + raise RuntimeError("test failed") + +commandline = sys.executable + " -m brave.robin" +run_except_on_windows(commandline , env = {"PYTHONPATH": "path2:path3"}) diff --git a/Examples/python/import_packages/namespace_pkg/zipsplit.py b/Examples/python/import_packages/namespace_pkg/zipsplit.py index 9e35559e3..30434f9c0 100644 --- a/Examples/python/import_packages/namespace_pkg/zipsplit.py +++ b/Examples/python/import_packages/namespace_pkg/zipsplit.py @@ -1,9 +1,25 @@ +import os +import subprocess import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) + +print(" Starting subtest " + os.path.basename(__file__)) + # Package brave split into two paths. # brave/robin.py (in path4.zip) and path3/brave/_robin.so -sys.path.insert(0, 'path4.zip') -sys.path.insert(0, 'path3') +sys.path.insert(0, "path4.zip") +sys.path.insert(0, "path3") from brave import robin +print(" Finished from brave import robin") -assert(robin.run() == "AWAY!") +if not(robin.run() == "AWAY!"): + raise RuntimeError("test failed") + +commandline = sys.executable + " -m brave.robin" +run_except_on_windows(commandline, env = {"PYTHONPATH": "path3:path4.zip"}) diff --git a/Examples/python/import_packages/relativeimport1/runme.py b/Examples/python/import_packages/relativeimport1/runme.py index 997476b1d..87101ea46 100644 --- a/Examples/python/import_packages/relativeimport1/runme.py +++ b/Examples/python/import_packages/relativeimport1/runme.py @@ -1,13 +1,32 @@ -import sys import os.path +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) # Test import of modules content from within __init__.py testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) with -relativeimport" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2.bar print " Finished importing py2.pkg2.bar" + commandline = sys.executable + " -m py2.pkg2.bar" + run_except_on_windows(commandline) + commandline = sys.executable + " -m py2.pkg2.pkg3.foo" + run_except_on_windows(commandline) else: import py3.pkg2.bar print " Finished importing py3.pkg2.bar" + commandline = sys.executable + " -m py3.pkg2.bar" + run_except_on_windows(commandline) + commandline = sys.executable + " -m py3.pkg2.pkg3.foo" + run_except_on_windows(commandline) diff --git a/Examples/python/import_packages/relativeimport2/runme.py b/Examples/python/import_packages/relativeimport2/runme.py index 9789afc18..f5b55782f 100644 --- a/Examples/python/import_packages/relativeimport2/runme.py +++ b/Examples/python/import_packages/relativeimport2/runme.py @@ -1,13 +1,32 @@ -import sys import os.path +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) # Test import of modules content from within __init__.py testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) + python 'import' in __init__.py" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2.bar print " Finished importing py2.pkg2.bar" + commandline = sys.executable + " -m py2.pkg2.bar" + run_except_on_windows(commandline) + commandline = sys.executable + " -m py2.pkg2.pkg3.pkg4.foo" + run_except_on_windows(commandline) else: import py3.pkg2.bar print " Finished importing py3.pkg2.bar" + commandline = sys.executable + " -m py3.pkg2.bar" + run_except_on_windows(commandline) + commandline = sys.executable + " -m py3.pkg2.pkg3.pkg4.foo" + run_except_on_windows(commandline) diff --git a/Examples/python/import_packages/relativeimport3/runme.py b/Examples/python/import_packages/relativeimport3/runme.py index 997476b1d..87101ea46 100644 --- a/Examples/python/import_packages/relativeimport3/runme.py +++ b/Examples/python/import_packages/relativeimport3/runme.py @@ -1,13 +1,32 @@ -import sys import os.path +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) # Test import of modules content from within __init__.py testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) with -relativeimport" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2.bar print " Finished importing py2.pkg2.bar" + commandline = sys.executable + " -m py2.pkg2.bar" + run_except_on_windows(commandline) + commandline = sys.executable + " -m py2.pkg2.pkg3.foo" + run_except_on_windows(commandline) else: import py3.pkg2.bar print " Finished importing py3.pkg2.bar" + commandline = sys.executable + " -m py3.pkg2.bar" + run_except_on_windows(commandline) + commandline = sys.executable + " -m py3.pkg2.pkg3.foo" + run_except_on_windows(commandline) diff --git a/Examples/python/import_packages/same_modnames1/runme.py b/Examples/python/import_packages/same_modnames1/runme.py index 3c3c00c1a..a64551bfd 100644 --- a/Examples/python/import_packages/same_modnames1/runme.py +++ b/Examples/python/import_packages/same_modnames1/runme.py @@ -1,4 +1,12 @@ import os.path +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) # Test import of same modules from different packages testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) @@ -10,10 +18,9 @@ print " Finished importing pkg2.foo" var2 = pkg2.foo.Pkg2_Foo() classname = str(type(var2)) -# Check for an old-style class if swig was run in -classic mode -if classname == "": - classname = str(var2.__class__) - if classname.find("pkg2.foo.Pkg2_Foo") == -1: raise RuntimeError("failed type checking: " + classname) print " Successfully created object pkg2.foo.Pkg2_Foo" + +commandline = sys.executable + " -m pkg2.foo" +run_except_on_windows(commandline) diff --git a/Examples/python/import_packages/same_modnames2/runme.py b/Examples/python/import_packages/same_modnames2/runme.py index 38daad0a3..c2cf2744c 100644 --- a/Examples/python/import_packages/same_modnames2/runme.py +++ b/Examples/python/import_packages/same_modnames2/runme.py @@ -1,4 +1,12 @@ import os.path +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) + python 'import' in __init__.py" @@ -9,10 +17,9 @@ print " Finished importing pkg1.pkg2.foo" var2 = pkg1.pkg2.foo.Pkg2_Foo() classname = str(type(var2)) -# Check for an old-style class if swig was run in -classic mode -if classname == "": - classname = str(var2.__class__) - if classname.find("pkg1.pkg2.foo.Pkg2_Foo") == -1: raise RuntimeError("failed type checking: " + classname) print " Successfully created object pkg1.pkg2.foo.Pkg2_Foo" + +commandline = sys.executable + " -m pkg1.pkg2.foo" +run_except_on_windows(commandline) diff --git a/Examples/python/import_packages/split_modules/Makefile b/Examples/python/import_packages/split_modules/Makefile index 65d635bb7..9eaaabd32 100644 --- a/Examples/python/import_packages/split_modules/Makefile +++ b/Examples/python/import_packages/split_modules/Makefile @@ -6,21 +6,21 @@ subdirs = vanilla vanilla_split check: build for s in $(subdirs); do \ - (cd $$s && $(MAKE) check); \ + (cd $$s && $(MAKE) check) || exit 1; \ done build: for s in $(subdirs); do \ - (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' build); \ + (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' build) || exit 1; \ done static: for s in $(subdirs); do \ - (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' static); \ + (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' static) || exit 1; \ done clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' python_clean for s in $(subdirs); do \ - (cd $$s && $(MAKE) clean); \ + (cd $$s && $(MAKE) clean) || exit 1; \ done diff --git a/Examples/python/import_packages/split_modules/README b/Examples/python/import_packages/split_modules/README index 0cb543e8a..d2ca15e7a 100644 --- a/Examples/python/import_packages/split_modules/README +++ b/Examples/python/import_packages/split_modules/README @@ -2,6 +2,9 @@ between two packages. Specifically the pure python part is part of a package and the C/C++ part is not in any package at all. Historically SWIG has supported this sort of thing. +From SWIG 4.0.0 onwards, split modules are not supported by default. +The %module directive needs to be customised with the moduleimport attribute +in order to import the a global C/C++ module. vanilla # "plane Jane" module both halves in pkg1 vanilla_split # python 1/2 in pkg1 C 1/2 in global namespace diff --git a/Examples/python/import_packages/split_modules/vanilla/runme.py b/Examples/python/import_packages/split_modules/vanilla/runme.py index a188364f1..79d79b4c3 100644 --- a/Examples/python/import_packages/split_modules/vanilla/runme.py +++ b/Examples/python/import_packages/split_modules/vanilla/runme.py @@ -1,4 +1,12 @@ import os.path +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - split modules" @@ -7,4 +15,8 @@ import pkg1.foo print " Finished importing pkg1.foo" -assert(pkg1.foo.count() == 3) +if not(pkg1.foo.count() == 3): + raise RuntimeError("test failed") + +commandline = sys.executable + " -m pkg1.foo" +run_except_on_windows(commandline) diff --git a/Examples/python/import_packages/split_modules/vanilla_split/Makefile b/Examples/python/import_packages/split_modules/vanilla_split/Makefile index c322b5aec..5d1c3521c 100644 --- a/Examples/python/import_packages/split_modules/vanilla_split/Makefile +++ b/Examples/python/import_packages/split_modules/vanilla_split/Makefile @@ -19,4 +19,6 @@ static: clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='foo' python_clean - cd pkg1 && $(MAKE) -f $(TOP)/../Makefile SRCDIR='$(SRCDIR)' TARGET='foo' python_clean + if test -d pkg1; then \ + cd pkg1 && $(MAKE) -f $(TOP)/../Makefile SRCDIR='$(SRCDIR)' TARGET='foo' python_clean; \ + fi diff --git a/Examples/python/import_packages/split_modules/vanilla_split/foo.i b/Examples/python/import_packages/split_modules/vanilla_split/foo.i index 60ce16ec3..81ad43a5b 100644 --- a/Examples/python/import_packages/split_modules/vanilla_split/foo.i +++ b/Examples/python/import_packages/split_modules/vanilla_split/foo.i @@ -1,4 +1,9 @@ -%module(package="pkg1") foo +#if defined(SWIGPYTHON_BUILTIN) /* defined when using -builtin */ +%module(package="pkg1", moduleimport="from $module import *") foo +#else +%module(package="pkg1", moduleimport="import $module") foo +#endif + %{ static unsigned count(void) { diff --git a/Examples/python/import_packages/split_modules/vanilla_split/runme.py b/Examples/python/import_packages/split_modules/vanilla_split/runme.py index a188364f1..79d79b4c3 100644 --- a/Examples/python/import_packages/split_modules/vanilla_split/runme.py +++ b/Examples/python/import_packages/split_modules/vanilla_split/runme.py @@ -1,4 +1,12 @@ import os.path +import subprocess +import sys + +def run_except_on_windows(commandline, env=None): + if os.name != "nt" and sys.platform != "cygwin": + # Strange failures on windows/cygin/mingw + subprocess.check_call(commandline, env=env, shell=True) + print(" Finished running: " + commandline) testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - split modules" @@ -7,4 +15,8 @@ import pkg1.foo print " Finished importing pkg1.foo" -assert(pkg1.foo.count() == 3) +if not(pkg1.foo.count() == 3): + raise RuntimeError("test failed") + +commandline = sys.executable + " -m pkg1.foo" +run_except_on_windows(commandline) diff --git a/Examples/python/java/Example.java b/Examples/python/java/Example.java deleted file mode 100644 index 91ddb1ac5..000000000 --- a/Examples/python/java/Example.java +++ /dev/null @@ -1,29 +0,0 @@ -public class Example { - public int mPublicInt; - - public Example() { - mPublicInt = 0; - } - - public Example(int IntVal) { - mPublicInt = IntVal; - } - - - public int Add(int a, int b) { - return (a+b); - } - - public float Add(float a, float b) { - return (a+b); - } - - public String Add(String a, String b) { - return (a+b); - } - - public Example Add(Example a, Example b) { - return new Example(a.mPublicInt + b.mPublicInt); - } -} - diff --git a/Examples/python/java/Makefile b/Examples/python/java/Makefile deleted file mode 100644 index 7c75e6b91..000000000 --- a/Examples/python/java/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -TOP = ../.. -SWIGEXE = $(TOP)/../swig -SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib -CXXSRCS = -TARGET = example -INTERFACE = example.i -LIBS = -lm - -check: build - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' python_run - -build: Example.class Example.h - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - CXXSHARED="gcj -fpic -shared Example.class" DEFS='' LIBS="-lstdc++" python_cpp - -clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' python_clean - rm -f $(TARGET).py - rm -f *.class Example.h - -Example.class Example.h: $(SRCDIR)Example.java - gcj -d . -fPIC -C -c -g $(SRCDIR)Example.java - gcjh Example.class diff --git a/Examples/python/java/example.i b/Examples/python/java/example.i deleted file mode 100644 index 80e08870f..000000000 --- a/Examples/python/java/example.i +++ /dev/null @@ -1,13 +0,0 @@ -%module example -%include - -%{ -#include "Example.h" -%} - - -%include Example.h - -%extend Example { - ~Example() {} -} diff --git a/Examples/python/java/runme.py b/Examples/python/java/runme.py deleted file mode 100644 index 641ba27dd..000000000 --- a/Examples/python/java/runme.py +++ /dev/null @@ -1,16 +0,0 @@ -from example import * - -JvCreateJavaVM(None) -JvAttachCurrentThread(None, None) - -e1 = Example(1) -e2 = Example(2) - -print e1.Add(1, 2) -print e1.Add(1.0, 2.0) -e3 = e1.Add(e1, e2) -print e3.mPublicInt - -print e1.Add("1", "2") - -JvDetachCurrentThread() diff --git a/Examples/python/libffi/example.i b/Examples/python/libffi/example.i index 9a29ec04e..3f5d766c5 100644 --- a/Examples/python/libffi/example.i +++ b/Examples/python/libffi/example.i @@ -20,7 +20,7 @@ PyObject *o = PyTuple_GetItem(varargs,i); if (!PyString_Check(o)) { PyErr_SetString(PyExc_ValueError,"Expected a string"); - return NULL; + SWIG_fail; } argv[i] = PyString_AsString(o); } @@ -58,11 +58,11 @@ &ffi_type_uint, types) == FFI_OK) { ffi_call(&cif, (void (*)()) execlp, &result, values); } else { - PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!"); free(types); free(values); free(arg3); - return NULL; + PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!"); + SWIG_fail; } free(types); free(values); @@ -107,9 +107,9 @@ int execlp(const char *path, const char *arg1, ...); argv[i].type = VT_POINTER; argv[i].val.pvalue = (void *) PyString_AsString(o); } else { - PyErr_SetString(PyExc_ValueError,"Unsupported argument type"); free(argv); - return NULL; + PyErr_SetString(PyExc_ValueError,"Unsupported argument type"); + SWIG_fail; } } @@ -157,11 +157,11 @@ int execlp(const char *path, const char *arg1, ...); &ffi_type_uint, types) == FFI_OK) { ffi_call(&cif, (void (*)()) printf, &result, values); } else { - PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!"); free(types); free(values); free(args); - return NULL; + PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!"); + SWIG_fail; } free(types); free(values); diff --git a/Examples/python/multimap/example.i b/Examples/python/multimap/example.i index 635f61c13..3ff5d52c0 100644 --- a/Examples/python/multimap/example.i +++ b/Examples/python/multimap/example.i @@ -39,7 +39,11 @@ extern int gcd(int x, int y); %#if PY_VERSION_HEX >= 0x03000000 { PyObject *utf8str = PyUnicode_AsUTF8String(s); - const char *cstr = PyBytes_AsString(utf8str); + const char *cstr; + if (!utf8str) { + SWIG_fail; + } + cstr = PyBytes_AsString(utf8str); $2[i] = strdup(cstr); Py_DECREF(utf8str); } @@ -69,9 +73,12 @@ extern int gcdmain(int argc, char *argv[]); PyObject *utf8str; if (!PyUnicode_Check($input)) { PyErr_SetString(PyExc_ValueError,"Expected a string"); - return NULL; + SWIG_fail; } utf8str = PyUnicode_AsUTF8String($input); + if (!utf8str) { + SWIG_fail; + } PyBytes_AsStringAndSize(utf8str, &cstr, &len); $1 = strncpy((char *)malloc(len+1), cstr, (size_t)len); $2 = (int)len; @@ -79,7 +86,7 @@ extern int gcdmain(int argc, char *argv[]); %#else if (!PyString_Check($input)) { PyErr_SetString(PyExc_ValueError,"Expected a string"); - return NULL; + SWIG_fail; } $1 = PyString_AsString($input); $2 = (int)PyString_Size($input); @@ -105,6 +112,9 @@ extern int count(char *bytes, int len, char c); char *cstr; Py_ssize_t len; PyObject *utf8str = PyUnicode_AsUTF8String($input); + if (!utf8str) { + SWIG_fail; + } PyBytes_AsStringAndSize(utf8str, &cstr, &len); $1 = strncpy((char *)malloc(len+1), cstr, (size_t)len); $2 = (int)len; diff --git a/Examples/python/operator/example.i b/Examples/python/operator/example.i index e37e76b3e..1e4b7ce34 100644 --- a/Examples/python/operator/example.i +++ b/Examples/python/operator/example.i @@ -17,6 +17,7 @@ %include "example.h" /* An output method that turns a complex into a short string */ +%feature("python:slot", "tp_str", functype="reprfunc") Complex::__str__; // For -builtin option to use __str__ in the tp_str slot %extend Complex { char *__str__() { static char temp[512]; diff --git a/Examples/python/performance/constructor/runme.py b/Examples/python/performance/constructor/runme.py index 1771fba7b..b00cd456c 100644 --- a/Examples/python/performance/constructor/runme.py +++ b/Examples/python/performance/constructor/runme.py @@ -1,5 +1,5 @@ import sys -sys.path.append('..') +sys.path.append("..") import harness diff --git a/Examples/python/performance/func/runme.py b/Examples/python/performance/func/runme.py index 760a8ab6d..3b142791c 100644 --- a/Examples/python/performance/func/runme.py +++ b/Examples/python/performance/func/runme.py @@ -1,5 +1,5 @@ import sys -sys.path.append('..') +sys.path.append("..") import harness diff --git a/Examples/python/performance/harness.py b/Examples/python/performance/harness.py index c3d38b4fb..3468faaad 100644 --- a/Examples/python/performance/harness.py +++ b/Examples/python/performance/harness.py @@ -17,16 +17,16 @@ def run(proc): except IndexError: proc = Popen( - [sys.executable, 'runme.py', 'Simple_baseline'], stdout=PIPE) + [sys.executable, "runme.py", "Simple_baseline"], stdout=PIPE) (stdout, stderr) = proc.communicate() print stdout proc = Popen( - [sys.executable, 'runme.py', 'Simple_optimized'], stdout=PIPE) + [sys.executable, "runme.py", "Simple_optimized"], stdout=PIPE) (stdout, stderr) = proc.communicate() print stdout proc = Popen( - [sys.executable, 'runme.py', 'Simple_builtin'], stdout=PIPE) + [sys.executable, "runme.py", "Simple_builtin"], stdout=PIPE) (stdout, stderr) = proc.communicate() print stdout diff --git a/Examples/python/performance/hierarchy/runme.py b/Examples/python/performance/hierarchy/runme.py index 8255cdc86..389958284 100644 --- a/Examples/python/performance/hierarchy/runme.py +++ b/Examples/python/performance/hierarchy/runme.py @@ -1,5 +1,5 @@ import sys -sys.path.append('..') +sys.path.append("..") import harness diff --git a/Examples/python/performance/hierarchy_operator/runme.py b/Examples/python/performance/hierarchy_operator/runme.py index eabfae864..48241d48b 100644 --- a/Examples/python/performance/hierarchy_operator/runme.py +++ b/Examples/python/performance/hierarchy_operator/runme.py @@ -1,5 +1,5 @@ import sys -sys.path.append('..') +sys.path.append("..") import harness diff --git a/Examples/python/performance/operator/runme.py b/Examples/python/performance/operator/runme.py index d75ae404c..798dd8bf9 100644 --- a/Examples/python/performance/operator/runme.py +++ b/Examples/python/performance/operator/runme.py @@ -1,5 +1,5 @@ import sys -sys.path.append('..') +sys.path.append("..") import harness diff --git a/Examples/python/pointer/index.html b/Examples/python/pointer/index.html index b99c8fe4c..ae52eddfd 100644 --- a/Examples/python/pointer/index.html +++ b/Examples/python/pointer/index.html @@ -145,7 +145,7 @@ extraction.

          Notes

          diff --git a/Examples/python/reference/index.html b/Examples/python/reference/index.html index 25d40299e..7ad39797b 100644 --- a/Examples/python/reference/index.html +++ b/Examples/python/reference/index.html @@ -121,7 +121,7 @@ Click here to see a SWIG interface file with these addit

          Sample Python script

          -Click here to see a script that manipulates some C++ references. +Click here to see a script that manipulates some C++ references.

          Notes:

          diff --git a/Examples/python/simple/index.html b/Examples/python/simple/index.html index dace471a3..a32f788f5 100644 --- a/Examples/python/simple/index.html +++ b/Examples/python/simple/index.html @@ -65,7 +65,7 @@ to create the extension examplemodule.so.

          Using the extension

          -Click here to see a script that calls our C functions from Python. +Click here to see a script that calls our C functions from Python.

          Key points

          diff --git a/Examples/python/std_vector/example.h b/Examples/python/std_vector/example.h index 4f0dac70d..52e260d6d 100644 --- a/Examples/python/std_vector/example.h +++ b/Examples/python/std_vector/example.h @@ -17,9 +17,8 @@ std::vector half(const std::vector& v) { } void halve_in_place(std::vector& v) { - // would you believe this is the same as the above? - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::vector::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } diff --git a/Examples/python/variables/index.html b/Examples/python/variables/index.html index 2940d8a6b..4efe34fcc 100644 --- a/Examples/python/variables/index.html +++ b/Examples/python/variables/index.html @@ -48,7 +48,7 @@ double foo;
    it will be accessed in the Python module as cvar.foo. Click -here to see a script that updates and prints +here to see a script that updates and prints out the values of the variables using this technique.

    Key points

    diff --git a/Examples/python/variables/runme.py b/Examples/python/variables/runme.py index 3388a0eba..4d34e92dd 100644 --- a/Examples/python/variables/runme.py +++ b/Examples/python/variables/runme.py @@ -48,18 +48,18 @@ example.print_vars() print "\nNow I'm going to try and modify some read only variables" -print " Tring to set 'path'" +print " Trying to set 'path'" try: example.cvar.path = "Whoa!" print "Hey, what's going on?!?! This shouldn't work" -except: +except Exception: print "Good." print " Trying to set 'status'" try: example.cvar.status = 0 print "Hey, what's going on?!?! This shouldn't work" -except: +except Exception: print "Good." diff --git a/Examples/ruby/check.list b/Examples/ruby/check.list index 2e581fb82..bdc2736ad 100644 --- a/Examples/ruby/check.list +++ b/Examples/ruby/check.list @@ -9,7 +9,6 @@ functor hashargs import import_template -java mark_function multimap operator diff --git a/Examples/ruby/exception_class/Makefile b/Examples/ruby/exceptproxy/Makefile similarity index 100% rename from Examples/ruby/exception_class/Makefile rename to Examples/ruby/exceptproxy/Makefile diff --git a/Examples/ruby/exception_class/example.h b/Examples/ruby/exceptproxy/example.h similarity index 93% rename from Examples/ruby/exception_class/example.h rename to Examples/ruby/exceptproxy/example.h index 9facde4bd..3ee6d765d 100644 --- a/Examples/ruby/exception_class/example.h +++ b/Examples/ruby/exceptproxy/example.h @@ -23,7 +23,7 @@ template class Queue { ~Queue() { delete [] items; } - void enqueue(T x) throw(FullError) { + void enqueue(T x) { if (nitems == maxsize) { throw FullError(maxsize); } @@ -43,9 +43,3 @@ template class Queue { } }; - - - - - - diff --git a/Examples/ruby/exception_class/example.i b/Examples/ruby/exceptproxy/example.i similarity index 94% rename from Examples/ruby/exception_class/example.i rename to Examples/ruby/exceptproxy/example.i index 5094b7a60..ad0c23acb 100644 --- a/Examples/ruby/exception_class/example.i +++ b/Examples/ruby/exceptproxy/example.i @@ -14,9 +14,10 @@ %} -/* The EmpytError doesn't appear in a throw declaration, and hence +/* The EmptyError doesn't appear in a throw declaration, and hence we need to tell SWIG that the dequeue method throws it. This can now be done via the %catchs feature. */ +%catches(FullError) *::enqueue; %catches(EmptyError) *::dequeue(); diff --git a/Examples/ruby/exception_class/runme.rb b/Examples/ruby/exceptproxy/runme.rb similarity index 100% rename from Examples/ruby/exception_class/runme.rb rename to Examples/ruby/exceptproxy/runme.rb diff --git a/Examples/ruby/free_function/runme.rb b/Examples/ruby/free_function/runme.rb index a517ed454..cf405d4cc 100644 --- a/Examples/ruby/free_function/runme.rb +++ b/Examples/ruby/free_function/runme.rb @@ -39,7 +39,11 @@ GC.start # C++ object ok = false begin - puts tiger2.get_name + # Let's stress the GC a bit, a single pass might not be enough. + 10.times { + GC.start + puts tiger2.get_name + } rescue ObjectPreviouslyDeleted => error ok = true end diff --git a/Examples/ruby/hashargs/example.i b/Examples/ruby/hashargs/example.i index 10e209e5f..4c3f3070b 100644 --- a/Examples/ruby/hashargs/example.i +++ b/Examples/ruby/hashargs/example.i @@ -2,13 +2,13 @@ %typemap(in) (int nattributes, const char **names, const int *values) (VALUE keys_ary, int i, VALUE key, VALUE val) { Check_Type($input, T_HASH); - $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL)); + $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil)); $2 = NULL; $3 = NULL; if ($1 > 0) { $2 = (char **) malloc($1*sizeof(char *)); $3 = (int *) malloc($1*sizeof(int)); - keys_ary = rb_funcall($input, rb_intern("keys"), 0, NULL); + keys_ary = rb_funcall($input, rb_intern("keys"), 0, Qnil); for (i = 0; i < $1; i++) { key = rb_ary_entry(keys_ary, i); val = rb_hash_aref($input, key); diff --git a/Examples/ruby/java/Example.java b/Examples/ruby/java/Example.java deleted file mode 100644 index 91ddb1ac5..000000000 --- a/Examples/ruby/java/Example.java +++ /dev/null @@ -1,29 +0,0 @@ -public class Example { - public int mPublicInt; - - public Example() { - mPublicInt = 0; - } - - public Example(int IntVal) { - mPublicInt = IntVal; - } - - - public int Add(int a, int b) { - return (a+b); - } - - public float Add(float a, float b) { - return (a+b); - } - - public String Add(String a, String b) { - return (a+b); - } - - public Example Add(Example a, Example b) { - return new Example(a.mPublicInt + b.mPublicInt); - } -} - diff --git a/Examples/ruby/java/Makefile b/Examples/ruby/java/Makefile deleted file mode 100644 index bec5e1844..000000000 --- a/Examples/ruby/java/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -TOP = ../.. -SWIGEXE = $(TOP)/../swig -SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib -CXXSRCS = -TARGET = example -INTERFACE = example.i -LIBS = -lm - -check: build - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run - -build: Example.class Example.h - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - CXXSHARED="gcj -fpic -shared Example.class" LIBS="-lstdc++" DEFS='' ruby_cpp - -clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean - rm -f *.class Example.h - -Example.class Example.h: $(SRCDIR)Example.java - gcj -d . -fPIC -C -c -g $(SRCDIR)Example.java - gcjh Example.class diff --git a/Examples/ruby/java/example.i b/Examples/ruby/java/example.i deleted file mode 100644 index 13d5b5e70..000000000 --- a/Examples/ruby/java/example.i +++ /dev/null @@ -1,9 +0,0 @@ -%module example -%include - -%{ -#include "Example.h" -%} - - -%include Example.h diff --git a/Examples/ruby/java/runme.rb b/Examples/ruby/java/runme.rb deleted file mode 100644 index fc018b70c..000000000 --- a/Examples/ruby/java/runme.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'example' - -Example.JvCreateJavaVM(nil) -Example.JvAttachCurrentThread(nil, nil) - -e1 = Example::Example.new(1) -e2 = Example::Example.new(2) - -print e1.Add(1,2),"\n" -print e1.Add(1.0,2.0),"\n" -e3 = e1.Add(e1,e2) -print e3.mPublicInt,"\n" - - -print e1.Add("1","2"),"\n" - -Example.JvDetachCurrentThread() - diff --git a/Examples/ruby/std_vector/example.h b/Examples/ruby/std_vector/example.h index 4f0dac70d..52e260d6d 100644 --- a/Examples/ruby/std_vector/example.h +++ b/Examples/ruby/std_vector/example.h @@ -17,9 +17,8 @@ std::vector half(const std::vector& v) { } void halve_in_place(std::vector& v) { - // would you believe this is the same as the above? - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::vector::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } diff --git a/Examples/ruby/variables/runme.rb b/Examples/ruby/variables/runme.rb index 38531c833..b748384ce 100644 --- a/Examples/ruby/variables/runme.rb +++ b/Examples/ruby/variables/runme.rb @@ -48,7 +48,7 @@ Example.print_vars() puts "\nNow I'm going to try and modify some read only variables"; -puts " Tring to set 'path'"; +puts " Trying to set 'path'"; begin Example.path = "Whoa!" puts "Hey, what's going on?!?! This shouldn't work" diff --git a/Examples/scilab/matrix2/example.i b/Examples/scilab/matrix2/example.i old mode 100755 new mode 100644 diff --git a/Examples/scilab/std_list/runme.sci b/Examples/scilab/std_list/runme.sci index e4c04b029..6075d7ac7 100644 --- a/Examples/scilab/std_list/runme.sci +++ b/Examples/scilab/std_list/runme.sci @@ -7,7 +7,7 @@ if ierr <> 0 then end example_Init(); -// This example shows how to use C++ fonctions with STL lists arguments +// This example shows how to use C++ functions with STL lists arguments // Here, STL lists are converted from/to Scilab matrices (SWIG_SCILAB_EXTRA_NATIVE_CONTAINERS is not defined) // integer lists diff --git a/Examples/scilab/std_vector/example.h b/Examples/scilab/std_vector/example.h index 4f0dac70d..52e260d6d 100644 --- a/Examples/scilab/std_vector/example.h +++ b/Examples/scilab/std_vector/example.h @@ -17,9 +17,8 @@ std::vector half(const std::vector& v) { } void halve_in_place(std::vector& v) { - // would you believe this is the same as the above? - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::vector::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } diff --git a/Examples/scilab/variables/runme.sci b/Examples/scilab/variables/runme.sci index 98d76cfa0..1ef077467 100644 --- a/Examples/scilab/variables/runme.sci +++ b/Examples/scilab/variables/runme.sci @@ -49,7 +49,7 @@ print_vars() // Immutable variables printf("\nNow I''m going to try and modify some read only variables\n"); -printf(" Tring to set ''path''\n"); +printf(" Trying to set ''path''\n"); try path_set("Whoa!"); printf("Hey, what''s going on?!?! This shouldn''t work\n"); diff --git a/Examples/tcl/check.list b/Examples/tcl/check.list index 8e7a8a9d7..31d26261b 100644 --- a/Examples/tcl/check.list +++ b/Examples/tcl/check.list @@ -5,7 +5,6 @@ contract enum funcptr import -java multimap operator pointer diff --git a/Examples/tcl/java/Example.java b/Examples/tcl/java/Example.java deleted file mode 100644 index 91ddb1ac5..000000000 --- a/Examples/tcl/java/Example.java +++ /dev/null @@ -1,29 +0,0 @@ -public class Example { - public int mPublicInt; - - public Example() { - mPublicInt = 0; - } - - public Example(int IntVal) { - mPublicInt = IntVal; - } - - - public int Add(int a, int b) { - return (a+b); - } - - public float Add(float a, float b) { - return (a+b); - } - - public String Add(String a, String b) { - return (a+b); - } - - public Example Add(Example a, Example b) { - return new Example(a.mPublicInt + b.mPublicInt); - } -} - diff --git a/Examples/tcl/java/Makefile b/Examples/tcl/java/Makefile deleted file mode 100644 index e4dfc536b..000000000 --- a/Examples/tcl/java/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -TOP = ../.. -SWIGEXE = $(TOP)/../swig -SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib -CXXSRCS = -TARGET = example -INTERFACE = example.i -LIBS = -lm - -check: build - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run - -build: Example.class Example.h - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ - TCLCXXSHARED="gcj -fpic -shared Example.class " LIBS="-lstdc++" DEFS='' tcl_cpp - -clean: - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean - rm -f *.class Example.h - -Example.class Example.h: $(SRCDIR)Example.java - gcj -d . -fPIC -C -c -g $(SRCDIR)Example.java - gcjh Example.class diff --git a/Examples/tcl/java/example.i b/Examples/tcl/java/example.i deleted file mode 100644 index b69d83f8d..000000000 --- a/Examples/tcl/java/example.i +++ /dev/null @@ -1,8 +0,0 @@ -%module example -%include - -%{ -#include "Example.h" -%} - -%include Example.h diff --git a/Examples/tcl/java/runme.tcl b/Examples/tcl/java/runme.tcl deleted file mode 100644 index 6caf0079f..000000000 --- a/Examples/tcl/java/runme.tcl +++ /dev/null @@ -1,15 +0,0 @@ -catch { load ./example[info sharedlibextension] example} - -JvCreateJavaVM NULL -JvAttachCurrentThread NULL NULL -Example e1 1 -Example e2 2 - -puts "[e1 cget -mPublicInt]" -puts "[e2 cget -mPublicInt]" - -puts "[e2 Add 1 2]" -puts "[e2 Add 1.0 2.0]" -puts "[e2 Add '1' '2']" - -JvDetachCurrentThread diff --git a/Examples/tcl/std_vector/example.h b/Examples/tcl/std_vector/example.h index 4f0dac70d..52e260d6d 100644 --- a/Examples/tcl/std_vector/example.h +++ b/Examples/tcl/std_vector/example.h @@ -17,9 +17,8 @@ std::vector half(const std::vector& v) { } void halve_in_place(std::vector& v) { - // would you believe this is the same as the above? - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::vector::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } diff --git a/Examples/tcl/variables/runme.tcl b/Examples/tcl/variables/runme.tcl index b9e2fd418..71aec38b8 100644 --- a/Examples/tcl/variables/runme.tcl +++ b/Examples/tcl/variables/runme.tcl @@ -48,7 +48,7 @@ print_vars puts "\nNow I'm going to try and modify some read only variables"; -puts " Tring to set 'path'"; +puts " Trying to set 'path'"; if { [catch { set path "Whoa!" puts "Hey, what's going on?!?! This shouldn't work" diff --git a/Examples/test-suite/README b/Examples/test-suite/README index aac7636c6..3b7cea477 100644 --- a/Examples/test-suite/README +++ b/Examples/test-suite/README @@ -47,6 +47,6 @@ testdir/README file. Further Documentation --------------------- -There is documentation about the test-suite and how to use use it in +There is documentation about the test-suite and how to use it in the SWIG documentation - Doc/Manual/Extending.html#Extending_test_suite. diff --git a/Examples/test-suite/allprotected.i b/Examples/test-suite/allprotected.i index 086cfb245..e9b4eb341 100644 --- a/Examples/test-suite/allprotected.i +++ b/Examples/test-suite/allprotected.i @@ -79,5 +79,9 @@ protected: }; int ProtectedBase::staticMemberVariable = 10; +class ProtectedDerived : public ProtectedBase { +public: + ProtectedDerived(const char *s) : ProtectedBase(s) {} +}; %} diff --git a/Examples/test-suite/autodoc.i b/Examples/test-suite/autodoc.i index a2d9f5b4e..9f4365ee1 100644 --- a/Examples/test-suite/autodoc.i +++ b/Examples/test-suite/autodoc.i @@ -1,5 +1,7 @@ %module(docstring="hello.") autodoc +%warnfilter(SWIGWARN_PARSE_KEYWORD) inout; + %feature("autodoc"); // special typemap and its docs @@ -74,6 +76,10 @@ %feature("autodoc","1") D::D(int a, int b, Hola h); // names + types %feature("autodoc","2") E::E(int a, int b, Hola h); // extended %feature("autodoc","3") F::F(int a, int b, Hola h); // extended + types +%feature("autodoc","0") C::~C(); // names +%feature("autodoc","1") D::~D(); // names + types +%feature("autodoc","2") E::~E(); // extended +%feature("autodoc","3") F::~F(); // extended + types %inline { @@ -133,6 +139,14 @@ typedef int Integer; void banana(S *a, const struct tagS *b, int c, Integer d) {} %} +// Check docs for a template type +%inline %{ +template struct T { + T inout(T t) { return t; } +}; +%} +%template(TInteger) T; + %inline %{ #ifdef SWIGPYTHON_BUILTIN bool is_python_builtin() { return true; } @@ -140,4 +154,32 @@ bool is_python_builtin() { return true; } bool is_python_builtin() { return false; } #endif %} - + +// Autodoc language keywords +%feature(autodoc,1) process; +%feature(autodoc,1) process2; +%feature("compactdefaultargs") process; +%feature("compactdefaultargs") process2; +%inline %{ +int process(int from, int in, int var) { return from; } +int process2(int from = 0, int _in = 1, int var = 2) { return from; } +%} + +%feature(autodoc,1) process3; +%feature(autodoc,1) process4; +%feature("kwargs") process3; +%feature("kwargs") process4; +%inline %{ +int process3(int from, int _in, int var) { return from; } +int process4(int from = 0, int _in = 1, int var = 2) { return from; } +%} + +// Autodoc for methods with default arguments not directly representable in +// target language. +%feature(autodoc,0) process_complex_defval; +%feature("compactdefaultargs") process_complex_defval; +%inline %{ +const int PROCESS_DEFAULT_VALUE = 17; +typedef long int some_type; +int process_complex_defval(int val = PROCESS_DEFAULT_VALUE, int factor = some_type(-1)) { return val*factor; } +%} diff --git a/Examples/test-suite/catches.i b/Examples/test-suite/catches.i index 8f09ae24c..89cf43f8d 100644 --- a/Examples/test-suite/catches.i +++ b/Examples/test-suite/catches.i @@ -1,9 +1,9 @@ %module catches +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW3(T1, T2, T3) throw(T1, T2, T3) %{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +#define TESTCASE_THROW3(T1, T2, T3) %} %include // for throws(...) typemap @@ -23,7 +23,7 @@ void test_catches(int i) { throw ThreeException(); } } -void test_exception_specification(int i) throw(int, const char *, const ThreeException&) { +void test_exception_specification(int i) TESTCASE_THROW3(int, const char *, const ThreeException&) { test_catches(i); } void test_catches_all(int i) { diff --git a/Examples/test-suite/class_scope_namespace.i b/Examples/test-suite/class_scope_namespace.i new file mode 100644 index 000000000..47d918157 --- /dev/null +++ b/Examples/test-suite/class_scope_namespace.i @@ -0,0 +1,160 @@ +// Test a mix of forward class declarations, class definitions, using declarations and using directives. + +%module class_scope_namespace + +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) H::HH; +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Space8::I_::II; + +%inline %{ +struct A; +namespace Space1 { + namespace SubSpace1 { + struct A { + void aa(Space1::SubSpace1::A, SubSpace1::A, A) {} + }; + void aaa(Space1::SubSpace1::A, SubSpace1::A, A) {} + } +} + +namespace Space2 { + struct B; +} +using Space2::B; +#ifdef __clang__ +namespace Space2 { + struct B { + void bb(Space2::B, B) {} + }; +} +#else +struct B { + void bb(Space2::B, B) {} +}; +#endif +void bbb(Space2::B, B) {} + +namespace Space3 { + namespace SubSpace3 { + struct C; + struct D; + } +} +struct C; +struct D; +namespace Space3 { + struct C; + struct SubSpace3::C { + void cc(Space3::SubSpace3::C, SubSpace3::C) {} + }; + using SubSpace3::D; + struct SubSpace3::D { + void dd(Space3::SubSpace3::D, SubSpace3::D, D) {} + }; + void ccc(Space3::SubSpace3::C, SubSpace3::C) {} + void ddd(Space3::SubSpace3::D, SubSpace3::D, D) {} +} + +namespace Space4 { + namespace SubSpace4 { + struct E; + } +} +using namespace Space4; +using SubSpace4::E; +// Was added to incorrect namespace in swig-3.0.12 +struct SubSpace4::E { + void ee(Space4::SubSpace4::E, SubSpace4::E, E) {} +}; +void eee(Space4::SubSpace4::E, SubSpace4::E, E) {} + +namespace Space5 { + namespace SubSpace5 { + namespace SubSubSpace5 { + struct F; + } + } +} +namespace Space5 { + using namespace SubSpace5; + using SubSubSpace5::F; + // Was added to incorrect namespace in swig-3.0.12 + struct SubSubSpace5::F { + void ff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {} + }; + void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {} +} + +namespace Space6 { + struct G; + namespace SubSpace6 { + struct G; + } +} +namespace Space6 { + struct SubSpace6::G { + void gg(Space6::SubSpace6::G, SubSpace6::G) {} + }; + void ggg(Space6::SubSpace6::G, SubSpace6::G) {} +} + +struct HH; +struct H { + struct HH { + void hh(H::HH) {} + }; +}; +void hhh(H::HH) {} + +namespace Space8 { + struct II; + struct I_ { + struct II { + void ii(Space8::I_::II, I_::II) {} + }; + }; + void iii(Space8::I_::II, I_::II) {} +} + +struct J; +namespace Space9 { + namespace SubSpace9 { + struct J { + void jj(Space9::SubSpace9::J, SubSpace9::J, J) {} + }; + void jjj(Space9::SubSpace9::J, SubSpace9::J, J) {} + } +} + +namespace Space10 { + struct K; +} +namespace Space10 { + namespace SubSpace10 { + struct K { + void kk(Space10::SubSpace10::K, SubSpace10::K, K) {} + }; + void kkk(Space10::SubSpace10::K, SubSpace10::K, K) {} + } +} + +namespace OtherSpace { + struct L; + struct M; +} +using OtherSpace::L; +namespace Space11 { + using OtherSpace::M; + namespace SubSpace11 { + struct L { + void ll(Space11::SubSpace11::L, SubSpace11::L, L) {} + }; + void lll(Space11::SubSpace11::L, SubSpace11::L, L) {} + struct M { + void mm(Space11::SubSpace11::M, SubSpace11::M, M) {} + }; + void mmm(Space11::SubSpace11::M, SubSpace11::M, M) {} + } +} + +%} + diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 10322b23b..822fc949c 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -83,13 +83,11 @@ Makefile: $(srcdir)/Makefile.in ../../../config.status # Broken C++ test cases. (Can be run individually using: make testcase.cpptest) CPP_TEST_BROKEN += \ constants \ - cpp_broken \ director_nested_class \ exception_partial_info \ extend_variable \ li_boost_shared_ptr_template \ nested_private \ - overload_complicated \ rename_camel \ template_default_pointer \ template_private_assignment \ @@ -99,7 +97,7 @@ CPP_TEST_BROKEN += \ # Broken C test cases. (Can be run individually using: make testcase.ctest) C_TEST_BROKEN += \ - tag_no_clash_with_variable + tag_no_clash_with_variable \ # C++ test cases. (Can be run individually using: make testcase.cpptest) CPP_TEST_CASES += \ @@ -136,6 +134,7 @@ CPP_TEST_CASES += \ char_binary \ char_strings \ chartest \ + class_scope_namespace \ class_forward \ class_ignore \ class_scope_weird \ @@ -162,13 +161,20 @@ CPP_TEST_CASES += \ cpp_nodefault \ cpp_static \ cpp_typedef \ + cpp14_binary_integer_literals \ + cpp17_hex_floating_literals \ + cpp17_nested_namespaces \ + cpp17_nspace_nested_namespaces \ + cpp17_u8_char_literals \ curiously_recurring_template_pattern \ default_args \ + default_arg_expressions \ default_arg_values \ default_constructor \ defvalue_constructor \ derived_byvalue \ derived_nested \ + destructor_methodmodifiers \ destructor_reprotected \ director_abstract \ director_alternating \ @@ -181,6 +187,8 @@ CPP_TEST_CASES += \ director_detect \ director_enum \ director_exception \ + director_exception_catches \ + director_exception_nothrow \ director_extend \ director_finalizer \ director_frob \ @@ -192,6 +200,7 @@ CPP_TEST_CASES += \ director_nspace_director_name_collision \ director_overload \ director_overload2 \ + director_ownership \ director_pass_by_value \ director_primitives \ director_property \ @@ -203,6 +212,7 @@ CPP_TEST_CASES += \ director_thread \ director_unroll \ director_using \ + director_void \ director_wombat \ disown \ dynamic_cast \ @@ -226,6 +236,7 @@ CPP_TEST_CASES += \ extend_placement \ extend_special_variables \ extend_template \ + extend_template_method \ extend_template_ns \ extend_typedef_class \ extern_c \ @@ -237,6 +248,7 @@ CPP_TEST_CASES += \ friends \ friends_template \ funcptr_cpp \ + functors \ fvirtual \ global_namespace \ global_ns_arg \ @@ -244,6 +256,7 @@ CPP_TEST_CASES += \ global_vars \ grouping \ ignore_parameter \ + import_fragments \ import_nomodule \ inherit \ inherit_member \ @@ -259,11 +272,11 @@ CPP_TEST_CASES += \ langobj \ li_attribute \ li_attribute_template \ - li_boost_array \ li_boost_shared_ptr \ - li_boost_shared_ptr_bits \ - li_boost_shared_ptr_template \ li_boost_shared_ptr_attribute \ + li_boost_shared_ptr_bits \ + li_boost_shared_ptr_director \ + li_boost_shared_ptr_template \ li_carrays_cpp \ li_cdata_cpp \ li_cpointer_cpp \ @@ -277,6 +290,7 @@ CPP_TEST_CASES += \ memberin_extend \ member_funcptr_galore \ member_pointer \ + member_pointer_const \ member_template \ minherit \ minherit2 \ @@ -288,6 +302,7 @@ CPP_TEST_CASES += \ multiple_inheritance_shared_ptr \ name_cxx \ name_warnings \ + namespace_chase \ namespace_class \ namespace_enum \ namespace_extend \ @@ -301,6 +316,7 @@ CPP_TEST_CASES += \ namespace_virtual_method \ nspace \ nspace_extend \ + native_directive \ naturalvar \ naturalvar_more \ naturalvar_onoff \ @@ -308,10 +324,13 @@ CPP_TEST_CASES += \ nested_directors \ nested_comment \ nested_ignore \ + nested_inheritance_interface \ + nested_in_template \ nested_scope \ nested_template_base \ nested_workaround \ newobject1 \ + newobject3 \ null_pointer \ operator_overload \ operator_overload_break \ @@ -320,10 +339,12 @@ CPP_TEST_CASES += \ ordering \ overload_arrays \ overload_bool \ + overload_complicated \ overload_copy \ overload_extend \ overload_method \ overload_numeric \ + overload_null \ overload_polymorphic \ overload_rename \ overload_return_type \ @@ -335,13 +356,13 @@ CPP_TEST_CASES += \ preproc_constants \ primitive_ref \ private_assign \ + proxycode \ protected_rename \ pure_virtual \ redefined \ redefined_not \ refcount \ reference_global_vars \ - register_par \ rename1 \ rename2 \ rename3 \ @@ -353,6 +374,7 @@ CPP_TEST_CASES += \ rename_pcre_encoder \ rename_pcre_enum \ rename_predicates \ + rename_wildcard \ restrict_cplusplus \ return_const_value \ return_value_scope \ @@ -386,9 +408,11 @@ CPP_TEST_CASES += \ static_array_member \ static_const_member \ static_const_member_2 \ + stl_no_default_constructor \ string_constants \ struct_initialization_cpp \ struct_value \ + swig_exception \ symbol_clash \ template_arg_replace \ template_arg_scope \ @@ -397,6 +421,7 @@ CPP_TEST_CASES += \ template_basic \ template_base_template \ template_classes \ + template_class_reuse_name \ template_const_ref \ template_construct \ template_templated_constructors \ @@ -406,11 +431,13 @@ CPP_TEST_CASES += \ template_default_arg_overloaded \ template_default_arg_overloaded_extend \ template_default_arg_virtual_destructor \ + template_default_cache \ template_default_class_parms \ template_default_class_parms_typedef \ template_default_inherit \ template_default_qualify \ template_default_vw \ + template_empty_inherit \ template_enum \ template_enum_ns_inherit \ template_enum_typedef \ @@ -427,6 +454,7 @@ CPP_TEST_CASES += \ template_methods \ template_namespace_forward_declaration \ template_using_directive_and_declaration_forward \ + template_using_directive_typedef \ template_nested \ template_nested_typemaps \ template_ns \ @@ -437,6 +465,7 @@ CPP_TEST_CASES += \ template_ns_enum2 \ template_ns_inherit \ template_ns_scope \ + template_parameters_global_scope \ template_partial_arg \ template_partial_specialization \ template_partial_specialization_typedef \ @@ -474,6 +503,7 @@ CPP_TEST_CASES += \ throw_exception \ typedef_array_member \ typedef_class \ + typedef_classforward_same_name \ typedef_funcptr \ typedef_inherit \ typedef_mptr \ @@ -486,6 +516,7 @@ CPP_TEST_CASES += \ typemap_array_qualifiers \ typemap_delete \ typemap_directorout \ + typemap_documentation \ typemap_global_scope \ typemap_manyargs \ typemap_namespace \ @@ -493,6 +524,8 @@ CPP_TEST_CASES += \ typemap_numinputs \ typemap_template \ typemap_template_parm_typedef \ + typemap_template_parms \ + typemap_template_typedef \ typemap_out_optimal \ typemap_qualifier_strip \ typemap_variables \ @@ -519,15 +552,18 @@ CPP_TEST_CASES += \ valuewrapper_opaque \ varargs \ varargs_overload \ + variable_replacement \ virtual_destructor \ + virtual_derivation \ virtual_poly \ virtual_vs_nonvirtual_base \ voidtest \ wallkw \ - wrapmacro + wrapmacro \ # C++11 test cases. -CPP11_TEST_CASES = \ +CPP11_TEST_CASES += \ + cpp11_alias_nested_template_scoping \ cpp11_alignment \ cpp11_alternate_function_syntax \ cpp11_constexpr \ @@ -535,23 +571,28 @@ CPP11_TEST_CASES = \ cpp11_default_delete \ cpp11_delegating_constructors \ cpp11_director_enums \ + cpp11_directors \ cpp11_explicit_conversion_operators \ + cpp11_final_directors \ cpp11_final_override \ cpp11_function_objects \ cpp11_inheriting_constructors \ cpp11_initializer_list \ cpp11_initializer_list_extend \ cpp11_lambda_functions \ - cpp11_li_std_array \ cpp11_noexcept \ cpp11_null_pointer_constant \ cpp11_raw_string_literals \ + cpp11_ref_qualifiers \ + cpp11_ref_qualifiers_rvalue_unignore \ + cpp11_ref_qualifiers_typemaps \ cpp11_result_of \ cpp11_rvalue_reference \ cpp11_rvalue_reference2 \ cpp11_rvalue_reference3 \ cpp11_sizeof_object \ cpp11_static_assert \ + cpp11_std_array \ cpp11_strongly_typed_enumerations \ cpp11_thread_local \ cpp11_template_double_brackets \ @@ -565,10 +606,35 @@ CPP11_TEST_CASES = \ # Broken C++11 test cases. CPP11_TEST_BROKEN = \ -# cpp11_hash_tables \ # not fully implemented yet # cpp11_variadic_templates \ # Broken for some languages (such as Java) # cpp11_reference_wrapper \ # No typemaps +# Doxygen support test cases: can only be used with languages supporting +# Doxygen comment translation, currently only Python and Java. +python_HAS_DOXYGEN := 1 +java_HAS_DOXYGEN := 1 + +$(eval HAS_DOXYGEN := $($(LANGUAGE)_HAS_DOXYGEN)) + +ifdef HAS_DOXYGEN +DOXYGEN_TEST_CASES += \ + doxygen_alias \ + doxygen_basic_notranslate \ + doxygen_basic_translate \ + doxygen_basic_translate_style2 \ + doxygen_ignore \ + doxygen_misc_constructs \ + doxygen_nested_class \ + doxygen_parsing \ + doxygen_parsing_enums \ + doxygen_translate \ + doxygen_translate_all_tags \ + doxygen_translate_links \ + +$(DOXYGEN_TEST_CASES:=.cpptest): SWIGOPT += -doxygen + +CPP_TEST_CASES += $(DOXYGEN_TEST_CASES) +endif # # Put all the heavy STD/STL cases here, where they can be skipped if needed @@ -585,15 +651,15 @@ CPP_STD_TEST_CASES += \ li_std_pair_using \ li_std_string \ li_std_vector \ + li_std_vector_back_reference \ li_std_vector_enum \ li_std_vector_member_var\ li_std_vector_ptr \ + li_std_wstring \ smart_pointer_inherit \ template_typedef_fnc \ template_type_namespace \ - template_opaque -# li_std_list - + template_opaque \ ifndef SKIP_CPP_STD_CASES CPP_TEST_CASES += ${CPP_STD_TEST_CASES} @@ -612,6 +678,7 @@ C_TEST_CASES += \ char_constant \ const_const \ constant_expr \ + default_args_c \ empty_c \ enums \ enum_forward \ @@ -645,8 +712,10 @@ C_TEST_CASES += \ preproc \ preproc_constants_c \ preproc_defined \ + preproc_gcc_output \ preproc_include \ preproc_line_file \ + register_par \ ret_by_value \ simple_array \ sizeof_pointer \ @@ -654,21 +723,22 @@ C_TEST_CASES += \ string_simple \ struct_rename \ struct_initialization \ + typedef_classforward_same_name \ typedef_struct \ typemap_subst \ union_parameter \ - unions + unions \ # Multi-module C++ test cases . (Can be run individually using make testcase.multicpptest) MULTI_CPP_TEST_CASES += \ clientdata_prop \ - imports \ import_stl \ - packageoption \ + imports \ mod \ + multi_import \ + packageoption \ template_typedef_import \ - multi_import # Custom tests - tests with additional commandline options wallkw.cpptest: SWIGOPT += -Wallkw @@ -717,6 +787,10 @@ check-cpp: $(CPP_TEST_CASES:=.cpptest) check-cpp11: $(CPP11_TEST_CASES:=.cpptest) +ifdef HAS_DOXYGEN +check-doxygen: $(DOXYGEN_TEST_CASES:=.cpptest) +endif + check-failing-test = \ $(MAKE) -s $1.$2 >/dev/null 2>/dev/null && echo "Failing test $1 passed." @@ -757,7 +831,7 @@ swig_and_compile_external = \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ TARGET='$*_wrap_hdr.h' \ - $(LANGUAGE)$(VARIANT)_externalhdr; \ + $(LANGUAGE)$(VARIANT)_externalhdr && \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS) $*_external.cxx' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ INCLUDES='$(INCLUDES)' SWIGOPT='$(SWIGOPT)' NOLINK=true \ @@ -771,7 +845,7 @@ setup = \ echo "$(ACTION)ing $(LANGUAGE) testcase $* (with run test)" ; \ else \ echo "$(ACTION)ing $(LANGUAGE) testcase $*" ; \ - fi; + fi diff --git a/Examples/test-suite/complextest.i b/Examples/test-suite/complextest.i index 64c751a82..592512b45 100644 --- a/Examples/test-suite/complextest.i +++ b/Examples/test-suite/complextest.i @@ -14,26 +14,53 @@ %template(VectorStdCplx) std::vector >; #endif -%inline +%inline { - std::complex Conj(const std::complex& a) + std::complex Conj(std::complex a) { return std::conj(a); - } + } - std::complex Conjf(const std::complex& a) + std::complex Conjf(std::complex a) { return std::conj(a); - } + } -#if 1 - std::vector > Copy_h(const std::vector >& a) + std::vector > CopyHalf(std::vector > a) { std::vector > b(a.size()/2); std::copy(a.begin(), a.begin()+a.size()/2, b.begin()); return b; - } -#endif + } + + using namespace std; + + struct ComplexPair + { + std::complex z1; + complex z2; + }; + + const complex& Conj2(const complex& a) + { + static complex ret; + ret = std::conj(a); + return ret; + } + + const complex& Conjf2(const complex& a) + { + static complex ret; + ret = std::conj(a); + return ret; + } + + const vector >& CopyHalfRef(const vector >& a) + { + static vector > b; + b = CopyHalf(a); + return b; + } } @@ -43,7 +70,7 @@ %{ %} -%inline +%inline { complex Conj(complex a) { diff --git a/Examples/test-suite/constant_directive.i b/Examples/test-suite/constant_directive.i index 89f13cecc..b102ffea2 100644 --- a/Examples/test-suite/constant_directive.i +++ b/Examples/test-suite/constant_directive.i @@ -2,6 +2,10 @@ // %constant and struct +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %inline %{ #if defined(_MSC_VER) #pragma warning(disable : 4190) // warning C4190: 'result' has C-linkage specified, but returns UDT 'Type1' which is incompatible with C diff --git a/Examples/test-suite/constructor_copy.i b/Examples/test-suite/constructor_copy.i index 7dcd05e8b..222c12f32 100644 --- a/Examples/test-suite/constructor_copy.i +++ b/Examples/test-suite/constructor_copy.i @@ -73,12 +73,18 @@ public: %include "std_vector.i" -#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGR) || defined(SWIGOCTAVE) || defined(SWIGRUBY) || defined(SWIGJAVASCRIPT) || defined(SWIGSCILAB) +#if defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGR) || defined(SWIGOCTAVE) || defined(SWIGRUBY) || defined(SWIGJAVASCRIPT) || defined(SWIGSCILAB) #define SWIG_GOOD_VECTOR %ignore std::vector::vector(size_type); %ignore std::vector::resize(size_type); #endif +#if defined(SWIGJAVA) +#define SWIG_GOOD_VECTOR +%ignore std::vector::vector(jint); +%ignore std::vector::resize(jint); +#endif + #if defined(SWIGTCL) || defined(SWIGPERL) #define SWIG_GOOD_VECTOR /* here, for languages with bad declaration */ diff --git a/Examples/test-suite/cplusplus_throw.i b/Examples/test-suite/cplusplus_throw.i index 3b11c48ca..72ae62938 100644 --- a/Examples/test-suite/cplusplus_throw.i +++ b/Examples/test-suite/cplusplus_throw.i @@ -5,10 +5,10 @@ %module cplusplus_throw +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) %{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +#define TESTCASE_THROW1(T1) %} %nodefaultctor; @@ -20,8 +20,8 @@ class Foo { }; class Bar { public: void baz() const { }; - void foo() throw (Foo) { }; - void bazfoo() const throw (int) { }; + void foo() TESTCASE_THROW1(Foo) { }; + void bazfoo() const TESTCASE_THROW1(int) { }; }; %} diff --git a/Examples/test-suite/cpp11_alias_nested_template_scoping.i b/Examples/test-suite/cpp11_alias_nested_template_scoping.i new file mode 100644 index 000000000..72814aa88 --- /dev/null +++ b/Examples/test-suite/cpp11_alias_nested_template_scoping.i @@ -0,0 +1,45 @@ +%module cpp11_alias_nested_template_scoping + +// Test to check a template parameter type is expanded when the template parameter +// is used twice in a type name. Expansion was +// Y< short >::YYY< T >::value_type > +// instead of +// Y< short >::YYY< short >::value_type > + +#if !defined(SWIGCSHARP) && !defined(SWIGJAVA) +%feature("flatnested") ZZZ; +#endif + +%inline %{ +template struct Y { + typedef T value_type; + typedef Y YY; + template using YYY = Y; + template struct ZZZ { + typedef T2 another_type; + }; + value_type create1() const { return T(); } + typename Y::value_type create2() const { return T(); } + typename Y::value_type create3() const { return T(); } + typename YY::value_type create4() const { return T(); } + typename Y::YY::value_type create5() const { return T(); } + Y::YYY::value_type create6() const { return T(); } + typename Y::template ZZZ::another_type create7() const { return T(); } + + // With global scope prefix + typename ::Y::value_type create13() const { return T(); } + + typename ::Y::YY::value_type create15() const { return T(); } + ::Y::YYY::value_type create16() const { return T(); } + typename ::Y::template ZZZ::another_type create17() const { return T(); } +}; +%} + +%extend Y { +%template() YYY; +%template() ZZZ; +}; +// Use above workaround instead of below (which currently gives syntax error) +// %template() Y::YYY; + +%template(Yshort) Y; diff --git a/Examples/test-suite/cpp11_alignment.i b/Examples/test-suite/cpp11_alignment.i index fb25c4ebb..135f63641 100644 --- a/Examples/test-suite/cpp11_alignment.i +++ b/Examples/test-suite/cpp11_alignment.i @@ -4,7 +4,8 @@ struct A { int member; }; -const int align1 = alignof(A::member); +const int align1 = alignof(int); +const int align2 = alignof(int *); %} %{ diff --git a/Examples/test-suite/cpp11_alternate_function_syntax.i b/Examples/test-suite/cpp11_alternate_function_syntax.i index 227a1c8c8..b3ecabc8c 100644 --- a/Examples/test-suite/cpp11_alternate_function_syntax.i +++ b/Examples/test-suite/cpp11_alternate_function_syntax.i @@ -6,13 +6,26 @@ struct SomeStruct { int addNormal(int x, int y); auto addAlternate(int x, int y) -> int; + auto addAlternateConst(int x, int y) const -> int; + auto addAlternateNoExcept(int x, int y) noexcept -> int; + auto addAlternateConstNoExcept(int x, int y) const noexcept -> int; + auto addAlternateMemberPtrParm(int x, int (SomeStruct::*mp)(int, int)) -> int; + auto addAlternateMemberPtrConstParm(int x, int (SomeStruct::*mp)(int, int) const) const -> int; + + virtual auto addFinal(int x, int y) const noexcept -> int final { return x + y; } + virtual ~SomeStruct() = default; }; -auto SomeStruct::addAlternate(int x, int y) -> int { - return x + y; +int SomeStruct::addNormal(int x, int y) { return x + y; } +auto SomeStruct::addAlternate(int x, int y) -> int { return x + y; } +auto SomeStruct::addAlternateConst(int x, int y) const -> int { return x + y; } +auto SomeStruct::addAlternateNoExcept(int x, int y) noexcept -> int { return x + y; } +auto SomeStruct::addAlternateConstNoExcept(int x, int y) const noexcept -> int { return x + y; } +auto SomeStruct::addAlternateMemberPtrParm(int x, int (SomeStruct::*mp)(int, int)) -> int { + return 100*x + (this->*mp)(x, x); +} +auto SomeStruct::addAlternateMemberPtrConstParm(int x, int (SomeStruct::*mp)(int, int) const) const -> int { + return 1000*x + (this->*mp)(x, x); } -int SomeStruct::addNormal(int x, int y) { - return x + y; -} %} diff --git a/Examples/test-suite/cpp11_constexpr.i b/Examples/test-suite/cpp11_constexpr.i index d91107cc6..420db4f83 100644 --- a/Examples/test-suite/cpp11_constexpr.i +++ b/Examples/test-suite/cpp11_constexpr.i @@ -3,11 +3,26 @@ */ %module cpp11_constexpr + +%{ +#if defined(__clang__) +#pragma clang diagnostic push +// Suppress: 'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const' to avoid a change in behavior +// For MMM() and NNN() +#pragma clang diagnostic ignored "-Wconstexpr-not-const" +#endif +%} + %inline %{ +#ifdef SWIG +#define SWIGTESTCONST const +#else +#define SWIGTESTCONST +#endif constexpr int AAA = 10; constexpr const int BBB = 20; constexpr int CCC() { return 30; } -constexpr const int DDD() { return 40; } +constexpr SWIGTESTCONST int DDD() { return 40; } constexpr int XXX() { return 10; } constexpr int YYY = XXX() + 100; @@ -17,7 +32,7 @@ struct ConstExpressions { static constexpr int KKK = 200; static const int LLL = 300; constexpr int MMM() { return 400; } - constexpr const int NNN() { return 500; } + constexpr SWIGTESTCONST int NNN() { return 500; } // Regression tests for support added in SWIG 3.0.4: static constexpr const int JJJ1 = 101; constexpr static int KKK1 = 201; diff --git a/Examples/test-suite/cpp11_default_delete.i b/Examples/test-suite/cpp11_default_delete.i index 79c02cddc..0c20fb7ee 100644 --- a/Examples/test-suite/cpp11_default_delete.i +++ b/Examples/test-suite/cpp11_default_delete.i @@ -17,20 +17,26 @@ public: }; struct A1 { - void func(int i) {} + void funk(int i) {} A1() = default; ~A1() = default; - void func(double i) = delete; /* Don't cast double to int. Compiler returns an error */ + void funk(double i) = delete; /* Don't cast double to int. Compiler returns an error */ private: A1(const A1&); }; A1::A1(const A1&) = default; struct A2 { - void func(int i) {} + void funk(int i) {} + +// Workaround clang 10.0.1 -std=c++17 linker error (oddly for Java and not Python): +// Undefined symbols for architecture x86_64:"___cxa_deleted_virtual", referenced from: vtable for A2 +#if !(defined(__clang__) && __cplusplus >= 201703L) virtual void fff(int) = delete; +#endif + virtual ~A2() = default; - template void func(T) = delete; + template void funk(T) = delete; }; struct trivial { diff --git a/Examples/test-suite/cpp11_directors.i b/Examples/test-suite/cpp11_directors.i new file mode 100644 index 000000000..3d1fbea25 --- /dev/null +++ b/Examples/test-suite/cpp11_directors.i @@ -0,0 +1,16 @@ +%module(directors="1") cpp11_directors +%feature("director"); + +%inline %{ + +class Foo { + public: + virtual ~Foo() noexcept {} + virtual int ping() noexcept = 0; + virtual int pong() noexcept = 0; + virtual int pang() const& noexcept = 0; + virtual int peng() & noexcept = 0; + virtual int pung() & = 0; +}; + +%} diff --git a/Examples/test-suite/cpp11_final_directors.i b/Examples/test-suite/cpp11_final_directors.i new file mode 100644 index 000000000..b58111adb --- /dev/null +++ b/Examples/test-suite/cpp11_final_directors.i @@ -0,0 +1,33 @@ +%module(directors="1") cpp11_final_directors + +%director Derived; + +// Check SWIG will not wrap these classes as directors where the destructors are final +%director BaseFinalDestructor; +%director BaseFinalDestructor2; + +%warnfilter(SWIGWARN_LANG_DIRECTOR_FINAL) BaseFinalDestructor::~BaseFinalDestructor; +%warnfilter(SWIGWARN_LANG_DIRECTOR_FINAL) BaseFinalDestructor2::~BaseFinalDestructor2; + +%inline %{ +struct Base { + virtual void basemeth() final {} + virtual ~Base() {} +}; + +struct Derived : Base { + virtual int derivedmeth() final { return 1; } + virtual int meth() { return 2; } + virtual ~Derived() {} +}; + +struct BaseFinalDestructor { + virtual void basefinalmeth() final {} + virtual ~BaseFinalDestructor() final {} +}; + +struct BaseFinalDestructor2 { + virtual void basefinalmeth() {} + virtual ~BaseFinalDestructor2() final {} +}; +%} diff --git a/Examples/test-suite/cpp11_final_override.i b/Examples/test-suite/cpp11_final_override.i index f691f8770..8d275b322 100644 --- a/Examples/test-suite/cpp11_final_override.i +++ b/Examples/test-suite/cpp11_final_override.i @@ -6,6 +6,12 @@ %warnfilter(SWIGWARN_PARSE_KEYWORD) final; // 'final' is a java keyword, renaming to '_final' %warnfilter(SWIGWARN_PARSE_KEYWORD) override; // 'override' is a C# keyword, renaming to '_override' +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) +%{ +#define TESTCASE_THROW1(T1) +%} + %inline %{ struct Base { @@ -16,6 +22,8 @@ struct Base { virtual void finaloverride2() {} virtual void finaloverride3() {} virtual void finaloverride4() const {} + virtual void finaloverride5() {} + virtual void finaloverride6() const {} virtual ~Base() {} }; @@ -31,6 +39,8 @@ struct Derived /*final*/ : Base { virtual void finaloverride2() override final {} virtual void finaloverride3() noexcept override final {} virtual void finaloverride4() const noexcept override final {} + virtual void finaloverride5() TESTCASE_THROW1(int) override final {} + virtual void finaloverride6() const TESTCASE_THROW1(int) override final {} virtual ~Derived() override final {} }; void Derived::override2() const noexcept {} @@ -78,6 +88,7 @@ struct Destructors4 : Base { struct FinalOverrideMethods { virtual void final() {} virtual void override(int) {} + virtual ~FinalOverrideMethods() = default; }; struct FinalOverrideVariables { int final; @@ -126,3 +137,4 @@ void DerivedNoVirtualStruct::cd() {} void DerivedNoVirtualStruct::ef() {} DerivedNoVirtualStruct::~DerivedNoVirtualStruct() {} %} + diff --git a/Examples/test-suite/cpp11_hash_tables.i b/Examples/test-suite/cpp11_hash_tables.i index 4f68cbac5..0c671aa5d 100644 --- a/Examples/test-suite/cpp11_hash_tables.i +++ b/Examples/test-suite/cpp11_hash_tables.i @@ -4,19 +4,27 @@ %inline %{ #include -//#include +#include #include -//#include +#include %} %include "std_set.i" -//%include "std_map.i" +%include "std_multiset.i" +%include "std_map.i" +%include "std_multimap.i" %include "std_unordered_set.i" -//%include "std_unordered_map.i" +%include "std_unordered_multiset.i" +%include "std_unordered_map.i" +%include "std_unordered_multimap.i" %template (SetInt) std::set; -//%template (MapIntInt) std::map; +%template (MultiSetInt) std::multiset; +%template (MapIntInt) std::map; +%template (MultiMapIntInt) std::multimap; %template (UnorderedSetInt) std::unordered_set; -//%template (UnorderedMapIntInt) std::unordered_map; +%template (UnorderedMultiSetInt) std::unordered_multiset; +%template (UnorderedMapIntInt) std::unordered_map; +%template (UnorderedMultiMapIntInt) std::unordered_multimap; %inline %{ using namespace std; @@ -25,19 +33,19 @@ class MyClass { public: set getSet() { return _set; } void addSet(int elt) { _set.insert(_set.begin(), elt); } -// map getMap() { return _map; } -// void addMap(int elt1, int elt2) { _map.insert(make_pair(elt1, elt2)); } + map getMap() { return _map; } + void addMap(int elt1, int elt2) { _map.insert(make_pair(elt1, elt2)); } unordered_set getUnorderedSet() { return _unordered_set; } void addUnorderedSet(int elt) { _unordered_set.insert(_unordered_set.begin(), elt); } -// unordered_map getUnorderedMap() { return _unordered_map; } -// void addUnorderedMap(int elt1, int elt2) { _unordered_map.insert(make_pair(elt1, elt2)); } + unordered_map getUnorderedMap() { return _unordered_map; } + void addUnorderedMap(int elt1, int elt2) { _unordered_map.insert(make_pair(elt1, elt2)); } private: set _set; -// map _map; + map _map; unordered_set _unordered_set; -// unordered_map _unordered_map; + unordered_map _unordered_map; }; %} diff --git a/Examples/test-suite/cpp11_initializer_list.i b/Examples/test-suite/cpp11_initializer_list.i index 58d2ecc50..b309576c1 100644 --- a/Examples/test-suite/cpp11_initializer_list.i +++ b/Examples/test-suite/cpp11_initializer_list.i @@ -6,12 +6,21 @@ %ignore A::A(std::initializer_list); %ignore B::method; -%typemap(in) std::initializer_list { +%typemap(in) std::initializer_list %{ $1 = {"Ab", "Fab"}; -} +%} + +%begin %{ +#if __GNUC__ >= 9 +/* warning: â€new’ of initializer_list does not extend the lifetime of the underlying array [-Winit-list-lifetime] */ +/* incorrect warning for C::C(std::initializer_list) */ +#pragma GCC diagnostic ignored "-Winit-list-lifetime" +#endif +%} %inline %{ #include +#include class A { public: @@ -26,9 +35,16 @@ public: void method(std::initializer_list init) {} }; class C { + std::string joined; public: - C(std::initializer_list) {} + C(std::initializer_list init) { + for (auto& val : init) + joined += val; + } C() {} + const char * get_joined_string() { + return joined.c_str(); + } }; %} diff --git a/Examples/test-suite/cpp11_lambda_functions.i b/Examples/test-suite/cpp11_lambda_functions.i index 161e08c65..3d7d76d60 100644 --- a/Examples/test-suite/cpp11_lambda_functions.i +++ b/Examples/test-suite/cpp11_lambda_functions.i @@ -26,6 +26,14 @@ %warnfilter(SWIGWARN_CPP11_LAMBDA) Space1::lambda19; %warnfilter(SWIGWARN_CPP11_LAMBDA) Space1::Space2::lambda20; +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW0() throw() +#define TESTCASE_THROW1(T1) throw(T1) +%{ +#define TESTCASE_THROW0() +#define TESTCASE_THROW1(T1) +%} + %inline %{ /* Defined lambda function with return value. */ auto lambda1 = [](int x, int y) -> int { return x+y; }; @@ -35,14 +43,17 @@ auto lambda1 = [](int x, int y) -> int { return x+y; }; single statement "return expr;". */ auto lambda2 = [](int x, int y) { return x+y; }; -auto lambda3 = [&](int x, int y) { return x+y; }; -auto lambda4 = [=](int x, int y) { return x+y; }; int thing = 0; #ifdef SWIG -// Not strictly correct as captured variables should have non-automatic storage duration, ie shouldn't capture globals. gcc-4.7 warns about this, but we check that SWIG can parse this anyway. +// This is not strictly legal: non-local lambda expression cannot have a capture-default +// gcc-4.7 warns about this and gcc-9 gives an error, but we check that SWIG can parse this anyway. +auto lambda3 = [&](int x, int y) { return x+y; }; +auto lambda4 = [=](int x, int y) { return x+y; }; auto lambda5 = [=,&thing]() { return thing; }; #else -auto lambda5 = [=]() { return thing; }; +auto lambda3 = [](int x, int y) { return x+y; }; +auto lambda4 = [](int x, int y) { return x+y; }; +auto lambda5 = []() { return thing; }; #endif void fn() { @@ -51,22 +62,27 @@ void fn() { } auto lambda6 = [] (int a, int b) mutable { return a + b; }; auto lambda7 = [] (int x, int y) -> int { return x+y; }; -auto lambda8 = [] (int x, int y) throw() -> int { return x+y; }; -auto lambda9 = [] (int x, int y) mutable throw() -> int { return x+y; }; -auto lambda10 = [] (int x, int y) throw(int) { return x+y; }; -auto lambda11 = [] (int x, int y) mutable throw(int) { return x+y; }; +auto lambda8 = [] (int x, int y) TESTCASE_THROW0() -> int { return x+y; }; +auto lambda9 = [] (int x, int y) mutable TESTCASE_THROW0() -> int { return x+y; }; +auto lambda10 = [] (int x, int y) TESTCASE_THROW1(int) { return x+y; }; +auto lambda11 = [] (int x, int y) mutable TESTCASE_THROW1(int) { return x+y; }; auto lambda12 = [] (int a, int b) { return a + b; }(1, 2); auto lambda13 = [] (int a, int b) mutable { return a + b; }(1, 2); -auto lambda14 = [] () throw () {}; -auto lambda15 = [] () mutable throw () {}; +auto lambda14 = [] () TESTCASE_THROW0() {}; +auto lambda15 = [] () mutable TESTCASE_THROW0() {}; auto lambda16 = [] { return thing; }; auto lambda17 = [] { return thing; }(); -constexpr auto lambda18 = [] (int x, int y) mutable throw(int) { return x+y; }; +#if defined(SWIG) || (defined(__cplusplus) && __cplusplus >= 201703L) +#define CONSTEXPR constexpr +#else +#define CONSTEXPR +#endif +CONSTEXPR auto lambda18 = [] (int x, int y) mutable TESTCASE_THROW1(int) { return x+y; }; namespace Space1 { - constexpr auto lambda19 = [] (int x, int y) mutable throw(int) { return x+y; }; + CONSTEXPR auto lambda19 = [] (int x, int y) mutable TESTCASE_THROW1(int) { return x+y; }; namespace Space2 { - constexpr auto lambda20 = [] (int x, int y) mutable throw(int) { return x+y; }; + CONSTEXPR auto lambda20 = [] (int x, int y) mutable TESTCASE_THROW1(int) { return x+y; }; } } @@ -102,6 +118,6 @@ int runLambdaInline() { // TODO int(*lambda101notauto)(int, int) = [] (int a, int b) { return a + b; }; int lambda102 = [] (int a, int b) mutable { return a + b; }(1, 2); -void lambda_init(int = ([=]{ return 0; })()); +void lambda_init(int = ([]{ return 0; })()); %} diff --git a/Examples/test-suite/cpp11_noexcept.i b/Examples/test-suite/cpp11_noexcept.i index ef96fd8a7..8aa0baa5a 100644 --- a/Examples/test-suite/cpp11_noexcept.i +++ b/Examples/test-suite/cpp11_noexcept.i @@ -3,9 +3,13 @@ %ignore NoExceptClass(NoExceptClass&&); %rename(Assignment) NoExceptClass::operator=; +%{ +extern "C" void global_noexcept(int, bool) noexcept {} +%} %inline %{ extern "C" void global_noexcept(int, bool) noexcept; +extern "C" void global_noexcept2(int, bool) noexcept {} struct NoExceptClass { static const bool VeryTrue = true; @@ -14,7 +18,7 @@ struct NoExceptClass { NoExceptClass(const NoExceptClass&) noexcept {} NoExceptClass(NoExceptClass&&) noexcept {} NoExceptClass& operator=(const NoExceptClass&) noexcept { return *this; } - ~NoExceptClass() noexcept {} + virtual ~NoExceptClass() noexcept {} void noex0() noexcept {} void noex1() noexcept(sizeof(int) == 4) {} @@ -27,8 +31,13 @@ struct NoExceptClass { void noo1() const noexcept {} static void noo2() noexcept {} virtual void noo3() const noexcept {} + +// Workaround clang 10.0.1 -std=c++17 linker error (oddly for Java and not Python): +// Undefined symbols for architecture x86_64: "___cxa_deleted_virtual", referenced from: vtable for NoExceptClass +#if !(defined(__clang__) && __cplusplus >= 201703L) virtual void noo4() const noexcept = delete; virtual void noo5() const throw() = delete; +#endif }; struct NoExceptAbstract { diff --git a/Examples/test-suite/cpp11_raw_string_literals.i b/Examples/test-suite/cpp11_raw_string_literals.i index 6fd13a0d0..b50b768b9 100644 --- a/Examples/test-suite/cpp11_raw_string_literals.i +++ b/Examples/test-suite/cpp11_raw_string_literals.i @@ -17,7 +17,9 @@ %warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) hh; %warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ii; +#if defined(SWIGTCL) || defined(SWIGCSHARP) || defined(SWIGOCTAVE) || defined(SWIGRUBY) || defined(SWIGPYTHON) || defined(SWIGJAVA) %include +#endif %inline %{ #include @@ -45,6 +47,9 @@ wstring aa = L"Wide string"; const char *bb = u8"UTF-8 string"; const char16_t *cc = u"UTF-16 string"; const char32_t *dd = U"UTF-32 string"; +// New char literals +char16_t char16_t_char = u'a'; +char32_t char32_t_char = U'b'; %} /* Raw string literals */ @@ -57,3 +62,43 @@ const char16_t *hh = uR"XXX(I'm a "raw UTF-16" \ string.)XXX"; const char32_t *ii = UR"XXX(I'm a "raw UTF-32" \ string.)XXX"; %} +// Constants +#if defined(SWIGJAVA) +%javaconst(1); +#elif SWIGCSHARP +%csconst(1); +#elif SWIGD +%dmanifestconst; +#endif + +%inline %{ +#define jj ")I'm an \"ascii\" \\ string constant." +#define kk R"XXX()I'm an "ascii" \ string constant.)XXX"; +%} + +%constant mm = R"XXX()I'm an "ascii" \ string constant with multiple + +lines.)XXX"; + +// docstring feature +%feature("docstring") RawStringDoc::WW "Single line documentation comment" +%feature("docstring") RawStringDoc::XX %{ +Multi-line +documentation +comment +%} +%feature("docstring") RawStringDoc::YY R"RRR(Single line "raw string" documentation comment)RRR" +%feature("docstring") RawStringDoc::ZZ R"FOO(Documentation comment + +as a "raw string" +on multiple lines including a \ backslash)FOO" + +%inline %{ +struct RawStringDoc { + void WW() {} + void XX() {} + void YY() {} + void ZZ() {} +}; +%} + diff --git a/Examples/test-suite/cpp11_ref_qualifiers.i b/Examples/test-suite/cpp11_ref_qualifiers.i new file mode 100644 index 000000000..e37136770 --- /dev/null +++ b/Examples/test-suite/cpp11_ref_qualifiers.i @@ -0,0 +1,226 @@ +%module cpp11_ref_qualifiers + +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ccextra2; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ccextra3; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc2; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc3; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc5; + +%include + +%ignore Host::h() const &; + +// Basic testing +%inline %{ +using std::string; +class Host { + string s; +public: + string h1() & { return string(); } + string h2() const & { return string(); } + string h3() && { return std::move(string()); } + string h4() const && { return std::move(string()); } + string h5() const { return string(); } + string h6() volatile const & { return string(); } + string h7() const volatile & { return string(); } + string h8() volatile const && { return std::move(string()); } + string h9() const volatile && { return std::move(string()); } + + string h() & { return string(); } + string h() const & { return string(); } + string h() && { return std::move(string()); } + string h() const && { return std::move(string()); } +}; +%} + +// %feature testing +%feature("except") F1() & %{ result = "F1"; %} +%feature("except") F2 %{ result = "F2"; %} +%feature("except") F3 %{ result = "F3"; %} +%feature("except") F3() %{ _should_not_be_used_ %} + +%feature("except") C1(int i) const & %{ result = "C1"; %} +%feature("except") C2 %{ result = "C2"; %} +%feature("except") C3 %{ result = "C3"; %} +%feature("except") C3(int i) %{ _should_not_be_used_ %} + +%inline %{ +struct Features { + string F1() & { return string(); } + string F2() & { return string(); } + string F3() & { return string(); } + + string C1(int i) const & { return string(); } + string C2(int i) const & { return string(); } + string C3(int i) const & { return string(); } +}; +%} + +// %rename testing +%rename(RR1) R1; +%rename(RR2) R2() &; +%rename(RR3) R3; +%rename(RR3Bad) R3(); + +%rename(SS1) S1; +%rename(SS2) S2(int i) const &; +%rename(SS3) S3; +%rename(SS3Bad) S3(int i); +%rename(SS3BadConst) S3(int i) const; +%rename(SS3BadLValue) S3(int i) &; + +%inline %{ +struct Renames { + string R1() & { return string(); } + string R2() & { return string(); } + string R3() & { return string(); } + + string S1(int i) const & { return string(); } + string S2(int i) const & { return string(); } + string S3(int i) const & { return string(); } +}; +%} + +// Conversion operators +%rename(StringConvertCopy) operator string() &; +%rename(StringConvertMove) operator string() &&; +%feature("ignore", "0") operator string() &&; // unignore as it is ignored by default + +%inline %{ +struct ConversionOperators { + virtual operator string() & { return string(); } + virtual operator string() && { return std::move(string()); } + virtual ~ConversionOperators() {} +}; +struct ConversionOperators2 { + virtual operator string() && { return std::move(string()); } + virtual ~ConversionOperators2() {} +}; +%} + +%inline %{ +struct Funcs { + short FF(bool) { return 0; } + short CC(bool) const & { return 0; } +}; + +class MemberFuncPtrs +{ +public: + // member ref-qualified function pointers, unnamed parameters + int aaa1(short (Funcs::*)(bool) &) const; + int aaa2(short (Funcs::* const *&)(bool) &) const; + int aaa3(short (Funcs::* *&)(bool) &) const; + int aaa4(short (Funcs::* *const&)(bool) &) const; + int aaa5(short (Funcs::* &)(bool) &) const; + int aaa6(short (Funcs::* const)(bool) &) const; + int aaa7(short (Funcs::* const&)(bool) &) const; + + int aaa8(short (Funcs::* const&)(bool) &&) const; + + // member cv-qualified and ref-qualified function pointers, unnamed parameters + int bbb1(short (Funcs::*)(bool) const &) const; + int bbb2(short (Funcs::* const *&)(bool) const &) const; + int bbb3(short (Funcs::* *&)(bool) const &) const; + int bbb4(short (Funcs::* *const&)(bool) const &) const; + int bbb5(short (Funcs::* &)(bool) const &) const; + int bbb6(short (Funcs::* const)(bool) const &) const; + int bbb7(short (Funcs::* const&)(bool) const &) const; + + int bbb8(short (Funcs::*)(bool) const &&) const; + + // member ref-qualified function pointers, named parameters + int qqq1(short (Funcs::* qq1)(bool) &) const; + int qqq2(short (Funcs::* const *& qq2)(bool) &) const; + int qqq3(short (Funcs::* *& qq3)(bool) &) const; + int qqq4(short (Funcs::* *const& qq4)(bool) &) const; + int qqq5(short (Funcs::* & qq5)(bool) &) const; + int qqq6(short (Funcs::* const qq6)(bool) &) const; + int qqq7(short (Funcs::* const& qq7)(bool) &) const; + + int qqq8(short (Funcs::* const& qq8)(bool) &&) const; + + // member cv-qualified and ref-qualified function pointers, named parameters + int rrr1(short (Funcs::* rr1)(bool) const &) const; + int rrr2(short (Funcs::* const *& rr2)(bool) const &) const; + int rrr3(short (Funcs::* *& rr3)(bool) const &) const; + int rrr4(short (Funcs::* *const& rr4)(bool) const &) const; + int rrr5(short (Funcs::* & rr5)(bool) const &) const; + int rrr6(short (Funcs::* const rr6)(bool) const &) const; + int rrr7(short (Funcs::* const& rr7)(bool) const &) const; + + int rrr8(short (Funcs::* rr1)(bool) const &&) const; +}; + +// member ref-qualified function pointers, unnamed parameters +int MemberFuncPtrs::aaa1(short (Funcs::*)(bool) &) const { return 0; } +int MemberFuncPtrs::aaa2(short (Funcs::* const *&)(bool) &) const { return 0; } +int MemberFuncPtrs::aaa3(short (Funcs::* *&)(bool) &) const { return 0; } +int MemberFuncPtrs::aaa4(short (Funcs::* *const&)(bool) &) const { return 0; } +int MemberFuncPtrs::aaa5(short (Funcs::* &)(bool) &) const { return 0; } +int MemberFuncPtrs::aaa6(short (Funcs::* const)(bool) &) const { return 0; } +int MemberFuncPtrs::aaa7(short (Funcs::* const&)(bool) &) const { return 0; } + +int MemberFuncPtrs::aaa8(short (Funcs::* const&)(bool) &&) const { return 0; } + +// member cv-qualified and ref-qualified function pointers, unnamed parameters +int MemberFuncPtrs::bbb1(short (Funcs::*)(bool) const &) const { return 0; } +int MemberFuncPtrs::bbb2(short (Funcs::* const *&)(bool) const &) const { return 0; } +int MemberFuncPtrs::bbb3(short (Funcs::* *&)(bool) const &) const { return 0; } +int MemberFuncPtrs::bbb4(short (Funcs::* *const&)(bool) const &) const { return 0; } +int MemberFuncPtrs::bbb5(short (Funcs::* &)(bool) const &) const { return 0; } +int MemberFuncPtrs::bbb6(short (Funcs::* const)(bool) const &) const { return 0; } +int MemberFuncPtrs::bbb7(short (Funcs::* const&)(bool) const &) const { return 0; } + +int MemberFuncPtrs::bbb8(short (Funcs::*)(bool) const &&) const { return 0; } + +// member ref-qualified function pointers, named parameters +int MemberFuncPtrs::qqq1(short (Funcs::* qq1)(bool) &) const { return 0; } +int MemberFuncPtrs::qqq2(short (Funcs::* const *& qq2)(bool) &) const { return 0; } +int MemberFuncPtrs::qqq3(short (Funcs::* *& qq3)(bool) &) const { return 0; } +int MemberFuncPtrs::qqq4(short (Funcs::* *const& qq4)(bool) &) const { return 0; } +int MemberFuncPtrs::qqq5(short (Funcs::* & qq5)(bool) &) const { return 0; } +int MemberFuncPtrs::qqq6(short (Funcs::* const qq6)(bool) &) const { return 0; } +int MemberFuncPtrs::qqq7(short (Funcs::* const& qq7)(bool) &) const { return 0; } + +int MemberFuncPtrs::qqq8(short (Funcs::* const& qq8)(bool) &&) const { return 0; } + +// member cv-qualified and ref-qualified function pointers, named parameters +int MemberFuncPtrs::rrr1(short (Funcs::* rr1)(bool) const &) const { return 0; } +int MemberFuncPtrs::rrr2(short (Funcs::* const *& rr2)(bool) const &) const { return 0; } +int MemberFuncPtrs::rrr3(short (Funcs::* *& rr3)(bool) const &) const { return 0; } +int MemberFuncPtrs::rrr4(short (Funcs::* *const& rr4)(bool) const &) const { return 0; } +int MemberFuncPtrs::rrr5(short (Funcs::* & rr5)(bool) const &) const { return 0; } +int MemberFuncPtrs::rrr6(short (Funcs::* const rr6)(bool) const &) const { return 0; } +int MemberFuncPtrs::rrr7(short (Funcs::* const& rr7)(bool) const &) const { return 0; } + +int MemberFuncPtrs::rrr8(short (Funcs::* rr1)(bool) const &&) const { return 0; } + +// member cv-qualified and ref-qualified pointer variables +short (Funcs::* cc1)(bool) const & = &Funcs::CC; + +short (Funcs::* const * ccextra2)(bool) const & = &cc1; +short (Funcs::* * ccextra3)(bool) const & = &cc1; +short (Funcs::* *const ccextra4)(bool) const & = &cc1; + +short (Funcs::* const *& cc2)(bool) const & = ccextra2; +short (Funcs::* *& cc3)(bool) const & = ccextra3; +short (Funcs::* *const& cc4)(bool) const & = ccextra4; +short (Funcs::* & cc5)(bool) const & = cc1; +short (Funcs::* const cc6)(bool) const & = &Funcs::CC; +short (Funcs::* const& cc7)(bool) const & = cc1; +%} + +%inline %{ + +struct Funktions { + int addByValue(const int &a, int b) const & { return a+b; } + int * addByPointer(const int &a, int b) const & { static int val; val = a+b; return &val; } + int & addByReference(const int &a, int b) const & { static int val; val = a+b; return val; } +}; + +int call1(int (Funktions::*d)(const int &, int) const &, int a, int b) { Funktions f; return (f.*d)(a, b); } +//int call2(int * (Funktions::*d)(const int &, int) const &, int a, int b) { Funktions f; return *(f.*d)(a, b); } +//int call3(int & (Funktions::*d)(const int &, int) const &, int a, int b) { Funktions f; return (f.*d)(a, b); } +%} +%constant int (Funktions::*ADD_BY_VALUE)(const int &, int) const & = &Funktions::addByValue; diff --git a/Examples/test-suite/cpp11_ref_qualifiers_rvalue_unignore.i b/Examples/test-suite/cpp11_ref_qualifiers_rvalue_unignore.i new file mode 100644 index 000000000..2f5fadfc6 --- /dev/null +++ b/Examples/test-suite/cpp11_ref_qualifiers_rvalue_unignore.i @@ -0,0 +1,15 @@ +%module cpp11_ref_qualifiers_rvalue_unignore + +// This is a minimal test that does not include any C++ headers to make sure the required +// header is generated from a fragment for the generated std::move call + +// m1 and m2 are ignored by default, unignore them +%feature("ignore", "0") RefQualifier::m1() &&; +%feature("ignore", "0") RefQualifier::m2() const &&; + +%inline %{ +struct RefQualifier { + void m1() && {} + void m2() const && {} +}; +%} diff --git a/Examples/test-suite/cpp11_ref_qualifiers_typemaps.i b/Examples/test-suite/cpp11_ref_qualifiers_typemaps.i new file mode 100644 index 000000000..0e1c3fe53 --- /dev/null +++ b/Examples/test-suite/cpp11_ref_qualifiers_typemaps.i @@ -0,0 +1,74 @@ +%module cpp11_ref_qualifiers_typemaps + +%typemap(in) SWIGTYPE (CLASS::*) %{ + _this_will_fail_to_compile_if_used_ +%} + +// typemaps to completely ignore the input parm and override it +%typemap(in) short (Funcs::*ff)(bool) const %{ $1 = &Funcs::FFF2; %} +%typemap(in) short (Funcs::*cc)(bool) & %{ $1 = &Funcs::CCC5; %} +%typemap(in) short (Funcs::*gg)(bool) const & %{ $1 = &Funcs::GGG8; %} +%typemap(in) short (Funcs::*hh)(bool) && %{ $1 = &Funcs::HHH11; %} + +%typemap(in) short (Funcs::*)(bool) const %{ $1 = &Funcs::FFF3; %} +%typemap(in) short (Funcs::*)(bool) & %{ $1 = &Funcs::CCC6; %} +%typemap(in) short (Funcs::*)(bool) const & %{ $1 = &Funcs::GGG9; %} +%typemap(in) short (Funcs::*)(bool) && %{ $1 = &Funcs::HHH12; %} + +%inline %{ +struct Funcs { + short FFF1(bool) const { return 1; } + short FFF2(bool) const { return 2; } + short FFF3(bool) const { return 3; } + short CCC4(bool) & { return 4; } + short CCC5(bool) & { return 5; } + short CCC6(bool) & { return 6; } + short GGG7(bool) const & { return 7; } + short GGG8(bool) const & { return 8; } + short GGG9(bool) const & { return 9; } + short HHH10(bool) && { return 10; } + short HHH11(bool) && { return 11; } + short HHH12(bool) && { return 12; } +}; +struct TypemapsNamedParms +{ + short fff(short (Funcs::*ff)(bool) const) { + Funcs funcs; + return (funcs.*ff)(true); + } + short ccc(short (Funcs::*cc)(bool) &) { + Funcs funcs; + return (funcs.*cc)(true); + } + short ggg(short (Funcs::*gg)(bool) const &) { + Funcs funcs; + return (funcs.*gg)(true); + } + short hhh(short (Funcs::*hh)(bool) &&) { + return (Funcs().*hh)(true); + } +}; +struct TypemapsUnnamedParms +{ + short fff(short (Funcs::*f)(bool) const) { + Funcs funcs; + return (funcs.*f)(true); + } + short ccc(short (Funcs::*c)(bool) &) { + Funcs funcs; + return (funcs.*c)(true); + } + short ggg(short (Funcs::*g)(bool) const &) { + Funcs funcs; + return (funcs.*g)(true); + } + short hhh(short (Funcs::*h)(bool) &&) { + return (Funcs().*h)(true); + } +}; +%} + +%constant short (Funcs::*FF1_MFP)(bool) const = &Funcs::FFF1; +%constant short (Funcs::*CC4_MFP)(bool) & = &Funcs::CCC4; +%constant short (Funcs::*GG7_MFP)(bool) const & = &Funcs::GGG7; +%constant short (Funcs::*HH10_MFP)(bool) && = &Funcs::HHH10; diff --git a/Examples/test-suite/cpp11_rvalue_reference2.i b/Examples/test-suite/cpp11_rvalue_reference2.i index 6718a3941..a2a0020f5 100644 --- a/Examples/test-suite/cpp11_rvalue_reference2.i +++ b/Examples/test-suite/cpp11_rvalue_reference2.i @@ -23,7 +23,7 @@ struct Thingy { int val; int &lvalref; int &&rvalref; - Thingy(int v) : val(v), lvalref(val), rvalref(22) {} + Thingy(int v, int &&rvalv) : val(v), lvalref(val), rvalref(std::move(rvalv)) {} void refIn(long &i) {} void rvalueIn(long &&i) {} short && rvalueInOut(short &&i) { return std::move(i); } @@ -31,8 +31,8 @@ struct Thingy { // test both primitive and user defined rvalue reference default arguments and compactdefaultargs void compactDefaultArgs(const bool &&b = (const bool &&)PublicGlobalTrue, const UserDef &&u = (const UserDef &&)PublicUserDef) {} void privateDefaultArgs(const bool &&b = (const bool &&)PrivateTrue) {} - operator int &&() { return std::move(0); } - Thingy(const Thingy& rhs) : val(rhs.val), lvalref(rhs.lvalref), rvalref(copy_int(rhs.rvalref)) {} + operator int &&() { return std::move(val); } + Thingy(const Thingy& rhs) : val(rhs.val), lvalref(rhs.lvalref), rvalref(std::move(rhs.rvalref)) {} Thingy& operator=(const Thingy& rhs) { val = rhs.val; lvalref = rhs.lvalref; @@ -41,23 +41,25 @@ struct Thingy { } private: static const bool PrivateTrue; - int copy_int(int& i) { return i; } Thingy(); }; const bool Thingy::PrivateTrue = true; short && globalRvalueInOut(short &&i) { return std::move(i); } -Thingy &&globalrrval = Thingy(55); +int glob = 123; -short && func(short &&i) { return std::move(i); } -Thingy getit() { return Thingy(22); } +Thingy &&globalrrval = Thingy(55, std::move(glob)); + +short && funk(short &&i) { return std::move(i); } +Thingy getit() { return Thingy(22, std::move(glob)); } void rvalrefFunction1(int &&v = (int &&)5) {} -void rvalrefFunctionBYVAL(short (Thingy::*memFunc)(short)) {} -void rvalrefFunctionLVALUE(short &(Thingy::*memFunc)(short &)) {} -void rvalrefFunction2(short && (Thingy::*memFunc)(short &&)) {} -void rvalrefFunction3(short && (*memFunc)(short &&)) {} +void rvalrefFunctionBYVAL(short (Thingy::*fptr)(short)) {} +void rvalrefFunctionPTR(short * (*fptr)(short *)) {} +void rvalrefFunctionLVALUE(short & (Thingy::*fptr)(short &)) {} +void rvalrefFunction2(short && (Thingy::*fptr)(short &&)) {} +void rvalrefFunction3(short && (*fptr)(short &&)) {} template struct RemoveReference { typedef T type; diff --git a/Examples/test-suite/cpp11_rvalue_reference3.i b/Examples/test-suite/cpp11_rvalue_reference3.i index c65309945..8ebf45366 100644 --- a/Examples/test-suite/cpp11_rvalue_reference3.i +++ b/Examples/test-suite/cpp11_rvalue_reference3.i @@ -26,12 +26,18 @@ void takeit5(Thing const*const&& t) {} struct Containing { Thing && member_rvalue_ref; - Thing *&& member_rvalue_ref_ptr1 = 0; - Thing const*&& member_rvalue_ref_ptr2 = 0; - Thing *const&& member_rvalue_ref_ptr3 = 0; - Thing const*const &&member_rvalue_ref_ptr4 = 0; + Thing *&& member_rvalue_ref_ptr1; + Thing const*&& member_rvalue_ref_ptr2; + Thing *const&& member_rvalue_ref_ptr3; + Thing const*const &&member_rvalue_ref_ptr4; - Containing() : member_rvalue_ref(Thing()) {} + Containing(Thing&&r, Thing*&& r1, Thing const*&& r2, Thing *const&& r3, Thing const*const && r4) : + member_rvalue_ref(std::move(r)), + member_rvalue_ref_ptr1(std::move(r1)), + member_rvalue_ref_ptr2(std::move(r2)), + member_rvalue_ref_ptr3(std::move(r3)), + member_rvalue_ref_ptr4(std::move(r4)) + {} }; %} @@ -57,11 +63,17 @@ void int_takeit5(int const*const&& t) {} struct IntContaining { int && member_rvalue_ref; - int *&& member_rvalue_ref_ptr1 = 0; - int const*&& member_rvalue_ref_ptr2 = 0; - int *const&& member_rvalue_ref_ptr3 = 0; - int const*const &&member_rvalue_ref_ptr4 = 0; + int *&& member_rvalue_ref_ptr1; + int const*&& member_rvalue_ref_ptr2; + int *const&& member_rvalue_ref_ptr3; + int const*const &&member_rvalue_ref_ptr4; - IntContaining() : member_rvalue_ref(55) {} + IntContaining(int&& r, int*&& r1, int const*&& r2, int *const&& r3, int const*const && r4) : + member_rvalue_ref(std::move(r)), + member_rvalue_ref_ptr1(std::move(r1)), + member_rvalue_ref_ptr2(std::move(r2)), + member_rvalue_ref_ptr3(std::move(r3)), + member_rvalue_ref_ptr4(std::move(r4)) + {} }; %} diff --git a/Examples/test-suite/cpp11_shared_ptr_const.i b/Examples/test-suite/cpp11_shared_ptr_const.i new file mode 100644 index 000000000..5e38123b4 --- /dev/null +++ b/Examples/test-suite/cpp11_shared_ptr_const.i @@ -0,0 +1,57 @@ +%module cpp11_shared_ptr_const + +%{ + +#include +#include + +class Foo +{ + int m; +public: + Foo(int i) : m(i) {} + int get_m() { return m;} +}; + +std::shared_ptr foo(Foo v) { + return std::shared_ptr(new Foo(v)); +} + +std::shared_ptr const_foo(Foo v) { + return std::shared_ptr(new Foo(v)); +} + +std::vector > foo_vec(Foo v) { + std::vector > result; + result.push_back( std::shared_ptr(new Foo(v)) ); + return result; +} + +std::vector > const_foo_vec(Foo v) { + std::vector > result; + result.push_back( std::shared_ptr(new Foo(v)) ); + return result; +} + +%} + +%include +%include + +%shared_ptr(Foo); + +%template (FooVector) std::vector >; +%template (FooConstVector) std::vector >; + +class Foo +{ + int m; +public: + Foo(int i); + int get_m(); +}; +std::shared_ptr foo(Foo v); +std::shared_ptr const_foo(Foo v); +std::vector > foo_vec(Foo v) const; +std::vector > const_foo_vec(Foo v) const; + diff --git a/Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i b/Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i new file mode 100644 index 000000000..2167dfb73 --- /dev/null +++ b/Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i @@ -0,0 +1,50 @@ +%module cpp11_shared_ptr_nullptr_in_containers + +%{ +#include +#include + +class C; +%} + +%include +%include + +%shared_ptr(C) + +%inline %{ + +class C { + int m; +public: + C() : m(-1) {} + C(int i) : m(i) {} + int get_m() { return m; } +}; + +%} + +%template() std::vector >; + +%inline %{ + + std::vector > ret_vec_c_shared_ptr() { + std::vector > ret(3); + ret[0] = std::shared_ptr(new C(0)); + ret[2] = std::shared_ptr(new C(2)); + return ret; + } + + std::vector > ret_arg_vec(const std::vector >& v) { + return v; + } + + bool is_last_null(const std::vector >& v) { + if( v.back() ) { + return false; + } else { + return true; + } + } + +%} diff --git a/Examples/test-suite/cpp11_shared_ptr_overload.i b/Examples/test-suite/cpp11_shared_ptr_overload.i new file mode 100644 index 000000000..ab84fda9a --- /dev/null +++ b/Examples/test-suite/cpp11_shared_ptr_overload.i @@ -0,0 +1,89 @@ +%module cpp11_shared_ptr_overload + +// Tests to ensure valid overloading in C++ between shared_ptr and other types result in code that compiles +// and all but the 1st overloaded method are automatically ignored/shadowed. +// Tests the 'equivalent' attribute in the 'typecheck' typemap. + +%include +%include + +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) UseA(std::shared_ptr mytype); +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) UseB(int, std::shared_ptr mytype); +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) UseC(int, std::shared_ptr mytype, std::shared_ptr); + +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) UseX(MyType &mytype); +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) UseY(int, MyType &mytype); +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) UseZ(int, MyType &mytype, std::shared_ptr); + +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) Combo1; +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) Combo2; +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) Combo3; +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) Combo4; +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) Combo5; +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) Combo6; +%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED,SWIGWARN_LANG_OVERLOAD_SHADOW) Combo7; + +%shared_ptr(MyType); + +%inline %{ +#include +#include +struct MyType { + std::string val; + MyType(std::string val = std::string()) : val(val) {} +}; + +// ref +std::string UseA(MyType &mytype) { return mytype.val + " ref"; } +std::string UseA(std::shared_ptr mytype) { return mytype->val + " sharedptr"; } + +std::string UseB(int, MyType &mytype) { return mytype.val + " ref"; } +std::string UseB(int, std::shared_ptr mytype) { return mytype->val + " sharedptr"; } + +std::string UseC(int, MyType &mytype, std::shared_ptr) { return mytype.val + " ref"; } +std::string UseC(int, std::shared_ptr mytype, std::shared_ptr) { return mytype->val + " sharedptr"; } + +// sharedptr +std::string UseX(std::shared_ptr mytype) { return mytype->val + " sharedptr"; } +std::string UseX(MyType &mytype) { return mytype.val + " ref"; } + +std::string UseY(int, std::shared_ptr mytype) { return mytype->val + " sharedptr"; } +std::string UseY(int, MyType &mytype) { return mytype.val + " ref"; } + +std::string UseZ(int, std::shared_ptr mytype, std::shared_ptr) { return mytype->val + " sharedptr"; } +std::string UseZ(int, MyType &mytype, std::shared_ptr) { return mytype.val + " ref"; } + +// Combo1-4 +std::string Combo1(MyType mytype) { return mytype.val + "Combo1"; } +std::string Combo1(MyType *mytype) { return ""; } +std::string Combo1(std::shared_ptr mytype) { return ""; } +std::string Combo1(std::shared_ptr* mytype) { return ""; } + +std::string Combo2(MyType *mytype) { return mytype->val + "Combo2"; } +std::string Combo2(std::shared_ptr mytype) { return ""; } +std::string Combo2(std::shared_ptr* mytype) { return ""; } +std::string Combo2(MyType mytype) { return ""; } + +std::string Combo3(std::shared_ptr mytype) { return mytype->val + "Combo3"; } +std::string Combo3(std::shared_ptr* mytype) { return ""; } +std::string Combo3(MyType mytype) { return ""; } +std::string Combo3(MyType *mytype) { return ""; } + +std::string Combo4(std::shared_ptr* mytype) { return (*mytype)->val + "Combo4"; } +std::string Combo4(MyType mytype) { return ""; } +std::string Combo4(MyType *mytype) { return ""; } +std::string Combo4(std::shared_ptr mytype) { return ""; } + +// Combo5-7 +std::string Combo5(MyType &mytype) { return mytype.val + "Combo5"; } +std::string Combo5(MyType *mytype) { return ""; } +std::string Combo5(std::shared_ptr mytype) { return ""; } + +std::string Combo6(MyType *mytype) { return mytype->val + "Combo6"; } +std::string Combo6(std::shared_ptr mytype) { return ""; } +std::string Combo6(MyType &mytype) { return ""; } + +std::string Combo7(std::shared_ptr mytype) { return mytype->val + "Combo7"; } +std::string Combo7(MyType &mytype) { return ""; } +std::string Combo7(MyType *mytype) { return ""; } +%} diff --git a/Examples/test-suite/cpp11_shared_ptr_upcast.i b/Examples/test-suite/cpp11_shared_ptr_upcast.i new file mode 100644 index 000000000..9d85f43d4 --- /dev/null +++ b/Examples/test-suite/cpp11_shared_ptr_upcast.i @@ -0,0 +1,188 @@ +%module cpp11_shared_ptr_upcast + +%{ +#include +#include +#include +#include +#include +#include +%} + +%include +%include +%include + +%{ + +class Base { + int m; +public: + Base() : m(-1) {} + Base(int i) : m(i) {} + int get_m() { return m; } +}; + +class Derived : public Base { + int n; +public: + Derived() : n(-2) {} + Derived(int i) : n(i) {} + int get_n() { return n; } +}; + +typedef std::shared_ptr BasePtr; +typedef std::shared_ptr DerivedPtr; + +// non-overloaded +int derived_num1(DerivedPtr v) { + return v == nullptr ? 999 : (*v).get_n(); +} + +int derived_num2(std::vector v) { + return v[0] == nullptr ? 999 : (*v[0]).get_n(); +} + +int derived_num3(std::map v) { + return v[0] == nullptr ? 999 : (*v[0]).get_n(); +} + +int base_num1(BasePtr v) { + return v == nullptr ? 999 : (*v).get_m(); +} + +int base_num2(std::vector v) { + return v[0] == nullptr ? 999 : (*v[0]).get_m(); +} + +int base_num3(std::map v) { + return v[0] == nullptr ? 999 : (*v[0]).get_m(); +} + +// overloaded +int derived_num(DerivedPtr v) { + return derived_num1(v); +} + +int derived_num(std::vector v) { + return derived_num2(v); +} + +int derived_num(std::map v) { + return derived_num3(v); +} + +int base_num(BasePtr v) { + return base_num1(v); +} + +int base_num(std::vector v) { + return base_num2(v); +} + +int base_num(std::map v) { + return base_num3(v); +} +%} + + +%shared_ptr(Base); +%shared_ptr(Derived); + +%template(BaseList) std::vector >; +%template(DerivedList) std::vector >; + +%template(BaseMap) std::map >; +%template(DerivedMap) std::map >; + +class Base { + int m; +public: + Base(); + int get_m(); +}; + +class Derived : public Base { + int n; +public: + Derived(); + Derived(int i); + int get_n(); +}; + +typedef std::shared_ptr BasePtr; +typedef std::shared_ptr DerivedPtr; + +// non-overloaded +int derived_num1(DerivedPtr); +int derived_num2(std::vector > v); +int derived_num3(std::map v); +int base_num1(BasePtr); +int base_num2(std::vector > v); +int base_num3(std::map v); + +// overloaded +int derived_num(DerivedPtr); +int derived_num(std::vector > v); +int derived_num(std::map v); +int base_num(BasePtr); +int base_num(std::vector > v); +int base_num(std::map v); + +// ptr to shared_ptr +%shared_ptr(Base2); +%shared_ptr(Derived2) + +%inline %{ +class Base2 { + int m; +public: + Base2() : m(-1) {} + Base2(int i) : m(i) {} + int get_m() { return m; } +}; + + +class Derived2 : public Base2 { + int n; +public: + Derived2() : n(0) {} + Derived2(int i) : n(i) {} + int get_n_2() { return n; } +}; +%} + +%template(Base2List) std::vector * >; +%template(Base2Map) std::map * >; + +%template(Derived2List) std::vector * >; +%template(Derived2Map) std::map * >; + +%inline %{ +typedef std::shared_ptr * Derived2Ptr; +typedef std::shared_ptr * Base2Ptr; + +int base2_num1(Base2Ptr v) { + return v == nullptr ? 999 : *v == nullptr ? 888 : (*v)->get_m(); +} + +int base2_num2(std::vector v) { + return v[0] == nullptr ? 999 : *v[0] == nullptr ? 888 : (*v[0])->get_m(); +} + +int base2_num3(std::map v) { + return v[0] == nullptr ? 999 : *v[0] == nullptr ? 888 : (*v[0])->get_m(); +} + +int derived2_num1(Derived2Ptr v) { + return v == nullptr ? 999 : *v == nullptr ? 888 : (*v)->get_n_2(); +} + +int derived2_num2(std::vector v) { + return v[0] == nullptr ? 999 : *v[0] == nullptr ? 888 : (*v[0])->get_n_2(); +} + +int derived2_num3(std::map v) { + return v[0] == nullptr ? 999 : *v[0] == nullptr ? 888 : (*v[0])->get_n_2(); +} +%} diff --git a/Examples/test-suite/cpp11_static_assert.i b/Examples/test-suite/cpp11_static_assert.i index 8d616f96c..7ca452d85 100644 --- a/Examples/test-suite/cpp11_static_assert.i +++ b/Examples/test-suite/cpp11_static_assert.i @@ -1,12 +1,32 @@ -/* This test case checks whether SWIG correctly parses and ignores the - keywords "static_assert()" inside the class or struct. +/* This test case checks whether SWIG correctly parses and ignores + "static_assert()" in various places. */ %module cpp11_static_assert %inline %{ +static_assert(sizeof(int) >= 2, "What? int size is invalid!"); + +namespace dummy { +// C++17 allows the message to be omitted, so check that works too. +// But only show the C++17 version to SWIG, as the compiler may +// lack C++17 support. +#ifdef SWIG +static_assert(sizeof(int) >= sizeof(short)); +#else +static_assert(sizeof(int) >= sizeof(short), "blah"); +#endif +} + template struct Check1 { static_assert(sizeof(int) <= sizeof(T), "not big enough"); + Check1() { +#ifdef SWIG + static_assert(true); +#else + static_assert(true, "true"); +#endif + } }; template diff --git a/Examples/test-suite/cpp11_li_std_array.i b/Examples/test-suite/cpp11_std_array.i similarity index 95% rename from Examples/test-suite/cpp11_li_std_array.i rename to Examples/test-suite/cpp11_std_array.i index 19304d9e6..3d4771551 100644 --- a/Examples/test-suite/cpp11_li_std_array.i +++ b/Examples/test-suite/cpp11_std_array.i @@ -1,6 +1,6 @@ -%module cpp11_li_std_array +%module cpp11_std_array -#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGJAVA) +#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGJAVA) || defined(SWIGCSHARP) %{ #include diff --git a/Examples/test-suite/cpp11_std_unordered_map.i b/Examples/test-suite/cpp11_std_unordered_map.i new file mode 100644 index 000000000..4bdec9c7c --- /dev/null +++ b/Examples/test-suite/cpp11_std_unordered_map.i @@ -0,0 +1,11 @@ +%module cpp11_std_unordered_map + +%include +%include + +%template(UnorderedMapIntInt) std::unordered_map; +%template(UnorderedMapStringInt) std::unordered_map; + +%inline %{ +std::unordered_map,std::equal_to< std::string >,std::allocator< std::pair< std::string const,int > > > inout(std::unordered_map m) { return m; } +%} diff --git a/Examples/test-suite/cpp11_std_unordered_multimap.i b/Examples/test-suite/cpp11_std_unordered_multimap.i new file mode 100644 index 000000000..8556b26b5 --- /dev/null +++ b/Examples/test-suite/cpp11_std_unordered_multimap.i @@ -0,0 +1,7 @@ +%module cpp11_std_unordered_multimap + +%include +%include + +%template(PairIntInt) std::pair; +%template(UnorderedMultiMapIntInt) std::unordered_multimap; diff --git a/Examples/test-suite/cpp11_std_unordered_multiset.i b/Examples/test-suite/cpp11_std_unordered_multiset.i new file mode 100644 index 000000000..c9907425e --- /dev/null +++ b/Examples/test-suite/cpp11_std_unordered_multiset.i @@ -0,0 +1,5 @@ +%module cpp11_std_unordered_multiset + +%include + +%template(UnorderedMultiSetInt) std::unordered_multiset; diff --git a/Examples/test-suite/cpp11_std_unordered_set.i b/Examples/test-suite/cpp11_std_unordered_set.i new file mode 100644 index 000000000..c2b8174bb --- /dev/null +++ b/Examples/test-suite/cpp11_std_unordered_set.i @@ -0,0 +1,7 @@ +%module cpp11_std_unordered_set + +%include +%include + +%template(UnorderedSetInt) std::unordered_set; +%template(UnorderedSetString) std::unordered_set; diff --git a/Examples/test-suite/cpp11_template_explicit.i b/Examples/test-suite/cpp11_template_explicit.i index f8fca4fae..71752f822 100644 --- a/Examples/test-suite/cpp11_template_explicit.i +++ b/Examples/test-suite/cpp11_template_explicit.i @@ -8,7 +8,8 @@ %inline %{ -template struct Temper { +template class Temper { +public: T val; }; @@ -18,14 +19,20 @@ public: int memberFunction() { return 100; } }; +class B { +public: + short member; + short memberFunction() { return 100; } +}; + template class Temper; -extern template class Temper; +extern template class Temper; template class Temper; -extern template class Temper; +extern template class Temper; template class Temper; -extern template class Temper; +extern template class Temper; %} %template(TemperInt) Temper; diff --git a/Examples/test-suite/cpp11_template_typedefs.i b/Examples/test-suite/cpp11_template_typedefs.i index 97a1da7ed..5f1f2e6f9 100644 --- a/Examples/test-suite/cpp11_template_typedefs.i +++ b/Examples/test-suite/cpp11_template_typedefs.i @@ -1,56 +1,86 @@ -/* This testcase checks whether SWIG correctly parses alias templates. */ +/* This testcase checks whether SWIG correctly handles alias templates. */ %module cpp11_template_typedefs -%warnfilter(SWIGWARN_CPP11_ALIAS_TEMPLATE) TypedefName; -%warnfilter(SWIGWARN_CPP11_ALIAS_TEMPLATE) TypedefNamePtr; -%warnfilter(SWIGWARN_CPP11_ALIAS_TEMPLATE) MyIntKeyClass; -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) PF; -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) BucketAllocator1; -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) BucketAllocator2; - -// This warning should go away when type aliasing is supported -#pragma SWIG nowarn=SWIGWARN_PARSE_USING_UNDEF // Nothing known about 'p.SomeType< char *,T2,4 >'. - %inline %{ -template< typename T1, typename T2, int > + +template +using ptr_t = T*; + +namespace ns { + +template class SomeType { +public: + using type1_t = T1; + using type2_t = T2; T1 a; T2 b; - int c; + constexpr int get_n() const { return N; } }; -// template aliasing -template< typename T2 > -using TypedefName = SomeType; -template< typename T2 > -using TypedefNamePtr = SomeType*; - -// type aliasing -typedef void (*PFD)(double); // Old style -using PF = void (*)(double); // New introduced syntax - - -// use of template aliasing -template -class MyCPP11Class { +// Specialization for T1=const char*, T2=bool +template +class SomeType { +public: + using type1_t = const char*; + using type2_t = bool; + type1_t a; + type2_t b; + constexpr int get_n() const { return 3 * N; } }; -template using MyIntKeyClass = MyCPP11Class; -MyIntKeyClass intchar; -TypedefName alias1(TypedefName a) { return a; } -TypedefNamePtr alias1(TypedefNamePtr a = nullptr) { return a; } -%} +// alias templates +template +using TypedefName = SomeType; +template +using TypedefNamePtr = ptr_t>; + +// alias template that returns T2 for a SomeType class +template +using T2_of = typename T::type2_t; + +T2_of> get_SomeType_b(const SomeType& x) { return x.b; } + +template +T2_of> get_SomeType_b2(const TypedefName& x) { return x.b; } + +} // namespace ns + +ns::TypedefName create_TypedefName() { return { "hello", 10}; } +ns::TypedefName create_TypedefNameBool() { return { "hello", true}; } +ns::TypedefNamePtr identity(ns::TypedefNamePtr a = nullptr) { return a; } -%inline %{ typedef double Val; template struct ListBucket { }; namespace Alloc { template struct rebind { - typedef int other; + using other = int; }; } using BucketAllocator1 = typename Alloc::template rebind>::other; using BucketAllocator2 = typename Alloc::template rebind<::template ListBucket>::other; + +BucketAllocator1 get_bucket_allocator1() { return 1; } +BucketAllocator2 get_bucket_allocator2() { return 2; } %} + +%immutable ns::SomeType::a; + +// %template() directives + +%template(SomeTypeInt5) ns::SomeType; +%template(SomeTypeInt4) ns::SomeType; +%template(SomeTypeBool5) ns::SomeType; + +%template(ListBucketDouble) ListBucket; +%template(RebindListBucketDouble) Alloc::rebind>; + +%template() ptr_t>; +%template() ns::TypedefName; +%template() ns::TypedefName; +%template() ns::TypedefNamePtr; +%template() ns::T2_of>; + +%template(get_SomeType_b2) ns::get_SomeType_b2; diff --git a/Examples/test-suite/cpp11_thread_local.i b/Examples/test-suite/cpp11_thread_local.i index 6a1019824..21f21859b 100644 --- a/Examples/test-suite/cpp11_thread_local.i +++ b/Examples/test-suite/cpp11_thread_local.i @@ -20,8 +20,10 @@ extern "C++" thread_local int ecpptval; thread_local int ThreadLocals::stval = 11; thread_local int ThreadLocals::tsval = 22; +#if !defined(_MSC_VER) thread_local const int ThreadLocals::stcval88; thread_local const int ThreadLocals::tscval99; +#endif %} %{ diff --git a/Examples/test-suite/cpp11_type_aliasing.i b/Examples/test-suite/cpp11_type_aliasing.i index 2f6ea3aa7..abc1642c4 100644 --- a/Examples/test-suite/cpp11_type_aliasing.i +++ b/Examples/test-suite/cpp11_type_aliasing.i @@ -108,5 +108,5 @@ PairSubclass::data_t plus1(PairSubclass::const_ref_data_t x) { return x + 1; } using callback_t = int(*)(int); callback_t get_callback() { return mult2; } -int call(callback_t func, int param) { return func(param); } +int call(callback_t funk, int param) { return funk(param); } %} diff --git a/Examples/test-suite/cpp14_binary_integer_literals.i b/Examples/test-suite/cpp14_binary_integer_literals.i new file mode 100644 index 000000000..9c696b5a5 --- /dev/null +++ b/Examples/test-suite/cpp14_binary_integer_literals.i @@ -0,0 +1,31 @@ +%module cpp14_binary_integer_literals + +// Tests are designed so that code compiles with C++98 compilers + +%{ +#if __cplusplus >= 201402L +#define CPP14 1 +#endif +%} + +int b1 = 0b1; +int b2 = 0b10; +long b3 = 0b11l; +unsigned long b4 = 0b100ul; +unsigned long b5 = 0B101UL; + +%{ +#if defined(CPP14) +int b1 = 0b1; +int b2 = 0b10; +long b3 = 0b11l; +unsigned long b4 = 0b100ul; +unsigned long b5 = 0B101UL; +#else +int b1 = 1; +int b2 = 2; +long b3 = 3; +unsigned long b4 = 4; +unsigned long b5 = 5; +#endif +%} diff --git a/Examples/test-suite/cpp17_hex_floating_literals.i b/Examples/test-suite/cpp17_hex_floating_literals.i new file mode 100644 index 000000000..dfc1dc0cf --- /dev/null +++ b/Examples/test-suite/cpp17_hex_floating_literals.i @@ -0,0 +1,43 @@ +%module cpp17_hex_floating_literals + +// Tests are designed so that code compiles with C++98 compilers + +%{ +#if __cplusplus >= 201703L +#define CPP17 1 +#endif +%} + +double f1 = 0x.0p1; +double f2 = 0x0.p1; +double f3 = 0x0.0p-1; +double f4 = 0xf.p-1; +double f5 = 0xA.0p1; +double f6 = 0x0.10P+10; +double f7 = 0xb2F.p2; +float f8 = 0x1234AP1F; +float f9 = 0x45A1.D1A2p+10f; + +%{ +#if defined(CPP17) +double f1 = 0x.0p1; +double f2 = 0x0.p1; +double f3 = 0x0.0p-1; +double f4 = 0xf.p-1; +double f5 = 0xA.0p1; +double f6 = 0x0.10P+10; +double f7 = 0xb2F.p2; +float f8 = 0x1234AP1F; +float f9 = 0x45A1.D1A2p+10f; +#else +double f1 = 0.; +double f2 = 0.; +double f3 = 0.; +double f4 = 7.5; +double f5 = 20.; +double f6 = 64.; +double f7 = 11452.; +float f8 = 149140.f; +float f9 = 18253638.f; +#endif +%} diff --git a/Examples/test-suite/cpp17_nested_namespaces.i b/Examples/test-suite/cpp17_nested_namespaces.i new file mode 100644 index 000000000..b9ec9bd5a --- /dev/null +++ b/Examples/test-suite/cpp17_nested_namespaces.i @@ -0,0 +1,199 @@ +%module cpp17_nested_namespaces +// Tests c++17 style nested namespaces +// Tests are designed so that code compiles with C++98 compilers + +#define CPP17 1 +%{ +#if __cplusplus >= 201703L +#define CPP17 1 +#endif +%} + +%inline %{ +// Tests with namespaces already defined using C++98 style (non-nested) namespaces +namespace A1 { + struct A1Struct { + void A1Method() {} + }; + namespace B1 { + struct B1Struct { + void B1Method() {} + }; + } +} +#if defined(CPP17) +namespace A1::B1 { +#else +namespace A1 { + namespace B1 { +#endif + A1Struct createA1Struct() { return ::A1::A1Struct(); } + B1Struct createB1Struct() { return ::A1::B1::B1Struct(); } +#if !defined(CPP17) + } +} +#else +} +#endif + +namespace A1 { + namespace B1 { + namespace C1 { + struct C1Struct { + void C1Method() {} + }; + } + } +} + +#if defined(CPP17) +namespace A1::B1::C1 { +#else +namespace A1 { + namespace B1 { + namespace C1 { +#endif + C1Struct createC1Struct() { return ::A1::B1::C1::C1Struct(); } +#if !defined(CPP17) + } + } +} +#else +} +#endif +%} + +%inline %{ +// Tests with namespaces already defined using C++17 style (nested) namespaces +#if defined(CPP17) +namespace A2::B2 { +#else +namespace A2 { + namespace B2 { +#endif + struct B2Struct { + void B2Method() {} + }; +#if !defined(CPP17) + } +} +#else +} +#endif + +#if defined(CPP17) +namespace A2::B2 { +#else +namespace A2 { + namespace B2 { +#endif + B2Struct createB2Struct() { return ::A2::B2::B2Struct(); } +#if !defined(CPP17) + } +} +#else +} +#endif + +#if defined(CPP17) +namespace A2::B2::C2 { +#else +namespace A2 { + namespace B2 { + namespace C2 { +#endif + struct C2Struct { + void C2Method() {} + }; +#if !defined(CPP17) + } + } +} +#else +} +#endif + +#if defined(CPP17) +namespace A2::B2::C2 { +#else +namespace A2 { + namespace B2 { + namespace C2 { +#endif + C2Struct createC2Struct() { return ::A2::B2::C2::C2Struct(); } +#if !defined(CPP17) + } + } +} +#else +} +#endif +%} + + +%inline %{ +// Tests with namespaces already defined using C++17 style (nested) namespaces to 3 levels +#if defined(CPP17) +namespace A3::B3::C3 { +#else +namespace A3 { + namespace B3 { + namespace C3 { +#endif + struct C3Struct { + void C3Method() {} + }; +#if !defined(CPP17) + } + } +} +#else +} +#endif + +#if defined(CPP17) +namespace A3::B3::C3 { +#else +namespace A3 { + namespace B3 { + namespace C3 { +#endif + C3Struct createC3Struct() { return ::A3::B3::C3::C3Struct(); } +#if !defined(CPP17) + } + } +} +#else +} +#endif + +#if defined(CPP17) +namespace A3::B3 { +#else +namespace A3 { + namespace B3 { +#endif + struct B3Struct { + void B3Method() {} + }; +#if !defined(CPP17) + } +} +#else +} +#endif + +#if defined(CPP17) +namespace A3::B3 { +#else +namespace A3 { + namespace B3 { +#endif + B3Struct createB3Struct() { return ::A3::B3::B3Struct(); } +#if !defined(CPP17) + } +} +#else +} +#endif +%} diff --git a/Examples/test-suite/cpp17_nspace_nested_namespaces.i b/Examples/test-suite/cpp17_nspace_nested_namespaces.i new file mode 100644 index 000000000..a88878de9 --- /dev/null +++ b/Examples/test-suite/cpp17_nspace_nested_namespaces.i @@ -0,0 +1,13 @@ +%module cpp17_nspace_nested_namespaces + +#if defined(SWIGJAVA) +SWIG_JAVABODY_PROXY(public, public, SWIGTYPE) +#endif + +// nspace feature only supported by these languages +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) || defined(SWIGLUA) || defined(SWIGJAVASCRIPT) +%nspace; +#endif + + +%include "cpp17_nested_namespaces.i" diff --git a/Examples/test-suite/cpp17_u8_char_literals.i b/Examples/test-suite/cpp17_u8_char_literals.i new file mode 100644 index 000000000..1aae1b231 --- /dev/null +++ b/Examples/test-suite/cpp17_u8_char_literals.i @@ -0,0 +1,26 @@ +%module cpp17_u8_char_literals + +// Tests are designed so that code compiles with C++98 compilers + +%{ +#if __cplusplus >= 201703L +#define CPP17 1 +#endif +%} + +// UTF-8 character literals will (apparently) have type char8_t in C++20. +char a = u8'a'; +char u = u8'u'; +char u8 = u8'8'; + +%{ +#if defined(CPP17) +char a = u8'a'; +char u = u8'u'; +char u8 = u8'8'; +#else +char a = 'a'; +char u = 'u'; +char u8 = '8'; +#endif +%} diff --git a/Examples/test-suite/cpp_broken.i b/Examples/test-suite/cpp_broken.i deleted file mode 100644 index 84d6122e5..000000000 --- a/Examples/test-suite/cpp_broken.i +++ /dev/null @@ -1,12 +0,0 @@ -%module cpp_broken - - -// bug #940318 -%inline %{ -typedef enum { -eZero = 0 -#define ONE 1 -} EFoo; -%} - - diff --git a/Examples/test-suite/cpp_namespace.i b/Examples/test-suite/cpp_namespace.i index d7bf95e9f..a415917db 100644 --- a/Examples/test-suite/cpp_namespace.i +++ b/Examples/test-suite/cpp_namespace.i @@ -2,6 +2,10 @@ %module cpp_namespace +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %inline %{ typedef int Bad; diff --git a/Examples/test-suite/cpp_static.i b/Examples/test-suite/cpp_static.i index c68e986eb..9ffe55837 100644 --- a/Examples/test-suite/cpp_static.i +++ b/Examples/test-suite/cpp_static.i @@ -10,6 +10,7 @@ Tests Sourceforge bug #444748. class StaticMemberTest { public: static int static_int; + static int grab_int() { return static_int; } }; class StaticFunctionTest { @@ -22,5 +23,30 @@ public: %} %{ -int StaticMemberTest::static_int; +int StaticMemberTest::static_int = 99; +%} + +%inline %{ +struct StaticBase { + static int statty; + static int grab_statty_base() { return statty; } + virtual ~StaticBase() {} +}; +struct StaticDerived : StaticBase { + static int statty; + static int grab_statty_derived() { return statty; } +}; +%} + +%{ +int StaticBase::statty = 11; +int StaticDerived::statty = 111; +%} + +%inline %{ +#ifdef SWIGPYTHON_BUILTIN +bool is_python_builtin() { return true; } +#else +bool is_python_builtin() { return false; } +#endif %} diff --git a/Examples/test-suite/csharp/Makefile.in b/Examples/test-suite/csharp/Makefile.in index 0c799c7d9..8272864d5 100644 --- a/Examples/test-suite/csharp/Makefile.in +++ b/Examples/test-suite/csharp/Makefile.in @@ -13,11 +13,13 @@ top_srcdir = ../@top_srcdir@ top_builddir = ../@top_builddir@ CPP_TEST_CASES = \ + complextest \ csharp_attributes \ csharp_swig2_compatibility \ csharp_exceptions \ csharp_features \ csharp_lib_arrays \ + csharp_lib_arrays_bool \ csharp_namespace_system_collision \ csharp_prepost \ csharp_typemaps \ @@ -25,9 +27,14 @@ CPP_TEST_CASES = \ enum_thorough_typesafe \ exception_partial_info \ intermediary_classname \ - li_boost_intrusive_ptr + li_boost_intrusive_ptr \ + li_std_list \ CPP11_TEST_CASES = \ + cpp11_shared_ptr_const \ + cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ + cpp11_shared_ptr_upcast \ cpp11_strongly_typed_enumerations_simple \ include $(srcdir)/../common.mk @@ -40,7 +47,9 @@ CSHARPFLAGSSPECIAL = # Custom tests - tests with additional commandline options intermediary_classname.cpptest: SWIGOPT += -dllimport intermediary_classname +complextest.cpptest: CSHARPFLAGSSPECIAL = -r:System.Numerics.dll csharp_lib_arrays.cpptest: CSHARPFLAGSSPECIAL = -unsafe +csharp_lib_arrays_bool.cpptest: CSHARPFLAGSSPECIAL = -unsafe csharp_swig2_compatibility.cpptest: SWIGOPT += -DSWIG2_CSHARP # Rules for the different types of tests diff --git a/Examples/test-suite/csharp/allprotected_runme.cs b/Examples/test-suite/csharp/allprotected_runme.cs index 99a791d58..6b04feb25 100644 --- a/Examples/test-suite/csharp/allprotected_runme.cs +++ b/Examples/test-suite/csharp/allprotected_runme.cs @@ -13,6 +13,20 @@ public class runme { MyProtectedBase mpb = new MyProtectedBase("MyProtectedBase"); mpb.accessProtected(); + try { + // C++ destructor is protected + mpb.Dispose(); + throw new Exception("failed to catch MethodAccessException"); + } catch (MethodAccessException) { + // Exception message: C++ destructor does not have public access + } + ProtectedDerived pd = new ProtectedDerived("ProtectedDerived"); + // Destroying via the ProtectedDerived's destructor should work + pd.Dispose(); + + ProtectedBase pb = new ProtectedDerived("ProtectedDerived"); + // ProtectedDerived's destructor should be called via the Dispose(disposing) virtual call + pb.Dispose(); } } diff --git a/Examples/test-suite/csharp/complextest_runme.cs b/Examples/test-suite/csharp/complextest_runme.cs new file mode 100644 index 000000000..e7af9c106 --- /dev/null +++ b/Examples/test-suite/csharp/complextest_runme.cs @@ -0,0 +1,43 @@ +// This is the complex runtime testcase. It checks that the C++ std::complex type works. +// It requires .NET 4.0 as the previous versions didn't have System.Numerics.Complex type. + +using System; +using System.Numerics; + +using complextestNamespace; + +public class complextest_runme { + + public static void Main() { + var a = new Complex(-1, 2); + if ( complextest.Conj(a) != Complex.Conjugate(a) ) + throw new Exception("std::complex test failed"); + + if ( complextest.Conjf(a) != Complex.Conjugate(a) ) + throw new Exception("std::complex test failed"); + + if ( complextest.Conj2(a) != Complex.Conjugate(a) ) + throw new Exception("std::complex test failed"); + + if ( complextest.Conjf2(a) != Complex.Conjugate(a) ) + throw new Exception("std::complex test failed"); + + var vec = new VectorStdCplx(); + vec.Add(new Complex(1, 2)); + vec.Add(new Complex(2, 3)); + vec.Add(new Complex(4, 3)); + vec.Add(new Complex(1, 0)); + + if ( complextest.CopyHalf(vec).Count != 2 ) + throw new Exception("CopyHalf test failed"); + + if ( complextest.CopyHalfRef(vec).Count != 2 ) + throw new Exception("CopyHalfRef test failed"); + + var p = new ComplexPair(); + p.z1 = new Complex(0, 1); + p.z2 = new Complex(0, -1); + if ( Complex.Conjugate(p.z2) != p.z1 ) + throw new Exception("vector test failed"); + } +} diff --git a/Examples/test-suite/csharp/cpp11_std_array_runme.cs b/Examples/test-suite/csharp/cpp11_std_array_runme.cs new file mode 100644 index 000000000..ee7c5ee24 --- /dev/null +++ b/Examples/test-suite/csharp/cpp11_std_array_runme.cs @@ -0,0 +1,82 @@ +// This test tests all the methods in the C# collection wrapper +using System; +using cpp11_std_arrayNamespace; + +public class cpp11_std_array_runme +{ + private static ArrayInt6 ToArray6(int[] a) + { + if (a.Length != 6) + throw new Exception("a is incorrect size"); + return new ArrayInt6(a); + } + + private static void compareContainers(ArrayInt6 actual, int[] expected) + { + if (actual.Count != expected.Length) + throw new Exception("Sizes are different: " + actual.Count + " " + expected.Length); + for (int i=0; i( T[] a, T[] b, string testName ) + { + if (a.Length != b.Length) + throw new Exception("size mismatch"); + + for(int i=0; i( T[] a ) + { + foreach ( T i in a ) + Console.Error.Write( "{0} ", i ); + Console.Error.WriteLine(); + } + + static bool runtimeIsMono() + { + return Type.GetType ("Mono.Runtime") != null; + } +} + diff --git a/Examples/test-suite/csharp/director_basic_runme.cs b/Examples/test-suite/csharp/director_basic_runme.cs index b9916108c..de299b145 100644 --- a/Examples/test-suite/csharp/director_basic_runme.cs +++ b/Examples/test-suite/csharp/director_basic_runme.cs @@ -48,6 +48,36 @@ public class runme if (myNewBar == null) throw new Exception("non-null pointer marshalling problem"); myNewBar.x = 10; + + // Low level implementation check +// my.testSwigDerivedClassHasMethod(); + + // These should not call the C# implementations as they are not overridden + int v; + v = MyClass.call_nonVirtual(my); + if (v != 100) throw new Exception("call_nonVirtual broken() " + v); + + v = MyClass.call_nonOverride(my); + if (v != 101) throw new Exception("call_nonOverride broken() " + v); + + // A mix of overridden and non-overridden + MyClassEnd myend = new MyClassEnd(); + MyClass mc = myend; + + v = mc.nonVirtual(); + if (v != 202) throw new Exception("mc.nonVirtual() broken " + v); + + v = MyClass.call_nonVirtual(mc); + if (v != 202) throw new Exception("call_nonVirtual(mc) broken " + v); + + v = MyClass.call_nonVirtual(myend); + if (v != 202) throw new Exception("call_nonVirtual(myend) broken" + v); + + v = MyClass.call_nonOverride(mc); + if (v != 101) throw new Exception("call_nonOverride(mc) broken" + v); + + v = MyClass.call_nonOverride(myend); + if (v != 101) throw new Exception("call_nonOverride(myend) broken" + v); } } } @@ -69,6 +99,30 @@ class MyOverriddenClass : MyClass { throw new Exception("null not received as expected"); return b; } + + public new bool nonVirtual() { + throw new Exception("non-virtual overrides virtual method"); + } + + public new virtual bool nonOverride() { + throw new Exception("non-override overrides virtual method"); + } +} + +class MyClassMiddle : MyClass { + public override int nonVirtual() { + return 202; + } +} + +class MyClassEnd : MyClassMiddle { + public new bool nonVirtual() { + throw new Exception("non-virtual overrides virtual method"); + } + + public new virtual bool nonOverride() { + throw new Exception("non-override overrides virtual method"); + } } } diff --git a/Examples/test-suite/csharp/director_classes_runme.cs b/Examples/test-suite/csharp/director_classes_runme.cs index 112561464..700492fb1 100644 --- a/Examples/test-suite/csharp/director_classes_runme.cs +++ b/Examples/test-suite/csharp/director_classes_runme.cs @@ -16,6 +16,7 @@ Expected output if PrintDebug enabled: Base - Val(444.555) Base - Ref(444.555) Base - Ptr(444.555) +Base - ConstPtrRef(444.555) Base - FullyOverloaded(int 10) Base - FullyOverloaded(bool 1) Base - SemiOverloaded(int -678) @@ -26,6 +27,7 @@ Base - DefaultParms(10, 1.1) Derived - Val(444.555) Derived - Ref(444.555) Derived - Ptr(444.555) +Derived - ConstPtrRef(444.555) Derived - FullyOverloaded(int 10) Derived - FullyOverloaded(bool 1) Derived - SemiOverloaded(int -678) @@ -36,6 +38,7 @@ Derived - DefaultParms(10, 1.1) CSharpDerived - Val(444.555) CSharpDerived - Ref(444.555) CSharpDerived - Ptr(444.555) +CSharpDerived - ConstPtrRef(444.555) CSharpDerived - FullyOverloaded(int 10) CSharpDerived - FullyOverloaded(bool True) CSharpDerived - SemiOverloaded(-678) @@ -59,7 +62,7 @@ public class runme void run() { - if (director_classes.PrintDebug) Console.WriteLine("------------ Start ------------ "); + if (director_classes.PrintDebug) Console.WriteLine("------------ Start ------------"); Caller myCaller = new Caller(); @@ -85,7 +88,7 @@ public class runme makeCalls(myCaller, myBase); } - if (director_classes.PrintDebug) Console.WriteLine("------------ Finish ------------ "); + if (director_classes.PrintDebug) Console.WriteLine("------------ Finish ------------"); } void makeCalls(Caller myCaller, Base myBase) @@ -99,6 +102,7 @@ public class runme if (myCaller.ValCall(dh).val != dh.val) throw new Exception("failed"); if (myCaller.RefCall(dh).val != dh.val) throw new Exception("failed"); if (myCaller.PtrCall(dh).val != dh.val) throw new Exception("failed"); + if (myCaller.ConstPtrRefCall(dh).val != dh.val) throw new Exception("failed"); // Fully overloaded method test (all methods in base class are overloaded) if (NAMESPACE + myCaller.FullyOverloadedCall(10) != myBase.GetType() + "::FullyOverloaded(int)") throw new Exception("failed"); @@ -142,6 +146,11 @@ public class CSharpDerived : Base if (director_classes.PrintDebug) Console.WriteLine("CSharpDerived - Ptr({0})", x.val); return x; } + public override DoubleHolder ConstPtrRef(DoubleHolder x) + { + if (director_classes.PrintDebug) Console.WriteLine("CSharpDerived - ConstPtrRef({0})", x.val); + return x; + } public override String FullyOverloaded(int x) { if (director_classes.PrintDebug) Console.WriteLine("CSharpDerived - FullyOverloaded(int {0})", x); diff --git a/Examples/test-suite/csharp/director_smartptr_runme.cs b/Examples/test-suite/csharp/director_smartptr_runme.cs index 559dff7a0..33037a1da 100644 --- a/Examples/test-suite/csharp/director_smartptr_runme.cs +++ b/Examples/test-suite/csharp/director_smartptr_runme.cs @@ -26,6 +26,29 @@ public class runme } } + private class director_smartptr_MyBarFooDerived : FooDerived + { + public override string ping() + { + return "director_smartptr_MyBarFooDerived.ping()"; + } + + public override string pong() + { + return "director_smartptr_MyBarFooDerived.pong();" + ping(); + } + + public override string upcall(FooBar fooBarPtr) + { + return "overrideDerived;" + fooBarPtr.FooBarDo(); + } + + public override Foo makeFoo() + { + return new Foo(); + } + } + private static void check(string got, string expected) { if (got != expected) @@ -49,5 +72,11 @@ public class runme Foo myFoo2 = new Foo().makeFoo(); check(myFoo2.pong(), "Foo::pong();Foo::ping()"); check(Foo.callPong(myFoo2), "Foo::pong();Foo::ping()"); + + FooDerived myBarFooDerived = new director_smartptr_MyBarFooDerived(); + check(myBarFooDerived.ping(), "director_smartptr_MyBarFooDerived.ping()"); + check(FooDerived.callPong(myBarFooDerived), "director_smartptr_MyBarFooDerived.pong();director_smartptr_MyBarFooDerived.ping()"); + check(FooDerived.callUpcall(myBarFooDerived, fooBar), "overrideDerived;Bar::Foo2::Foo2Bar()"); + } } diff --git a/Examples/test-suite/csharp/director_void_runme.cs b/Examples/test-suite/csharp/director_void_runme.cs new file mode 100644 index 000000000..24b470f11 --- /dev/null +++ b/Examples/test-suite/csharp/director_void_runme.cs @@ -0,0 +1,83 @@ +using System; +using director_voidNamespace; + +public class runme +{ + private static void WaitForGC() + { + System.GC.Collect(); + System.GC.WaitForPendingFinalizers(); + System.Threading.Thread.Sleep(10); + } + + static void Main() + { + runme r = new runme(); + r.run(); + } + + void run() + { + Caller caller = new Caller(); + { + DirectorVoidPointer dvp = new DirectorVoidPointer(5); + int x = caller.callVirtualIn(dvp, 6); + if (x != 106) + throw new Exception("Fail1 should be 106, got " + x); + global::System.IntPtr ptr = dvp.nonVirtualVoidPtrOut(); + x = Caller.VoidToInt(ptr); + if (x != 106) + throw new Exception("Fail2 should be 106, got " + x); + x = Caller.VoidToInt(dvp.voidPtrOut()); + if (x != 106) + throw new Exception("Fail3 should be 106, got " + x); + } + + { + DirectorVoidPointer dvp = new director_void_VoidPointer(5); + int x = caller.callVirtualIn(dvp, 6); + if (x != 12) + throw new Exception("Fail1 should be 12, got " + x); + global::System.IntPtr ptr = dvp.nonVirtualVoidPtrOut(); + x = Caller.VoidToInt(ptr); + if (x != 25) + throw new Exception("Fail2 should be 25, got " + x); + x = Caller.VoidToInt(dvp.voidPtrOut()); + if (x != 1234) + throw new Exception("Fail3 should be 1234, got " + x); + } + + { + DirectorVoidPointer dvp = new DirectorVoidPointer(10); + int x = caller.callVirtualOut(dvp); + if (x != 10) + throw new Exception("Bad1 should be 10, got " + x); + global::System.IntPtr ptr = dvp.nonVirtualVoidPtrOut(); + x = dvp.nonVirtualVoidPtrIn(ptr); + if (x != 110) + throw new Exception("Bad2 should be 110, got " + x); + } + { + DirectorVoidPointer dvp = new director_void_VoidPointer(10); + int x = caller.callVirtualOut(dvp); + if (x != 1234) + throw new Exception("Bad3 should be 1234, got " + x); + global::System.IntPtr ptr = dvp.nonVirtualVoidPtrOut(); + x = dvp.nonVirtualVoidPtrIn(ptr); + if (x != 1334) + throw new Exception("Bad4 should be 1334, got " + x); + } + } +} + +class director_void_VoidPointer : DirectorVoidPointer { + public director_void_VoidPointer(int num) : base(num*num) { + } + public override int voidPtrIn(global::System.IntPtr p) { + return Caller.VoidToInt(p) * 2; + } + public override global::System.IntPtr voidPtrOut() { + setNewValue(1234); + return nonVirtualVoidPtrOut(); + } +} diff --git a/Examples/test-suite/csharp/enum_thorough_typesafe_runme.cs b/Examples/test-suite/csharp/enum_thorough_typesafe_runme.cs index 86179dcf4..82c52a31f 100644 --- a/Examples/test-suite/csharp/enum_thorough_typesafe_runme.cs +++ b/Examples/test-suite/csharp/enum_thorough_typesafe_runme.cs @@ -405,6 +405,10 @@ public class runme { if (enum_thorough_typesafe.repeatTest(repeat.llast).swigValue != 3) throw new Exception("repeatTest 5 failed"); if (enum_thorough_typesafe.repeatTest(repeat.end).swigValue != 3) throw new Exception("repeatTest 6 failed"); } + { + if (enum_thorough_typesafe.enumWithMacroTest(enumWithMacro.ABCD).swigValue != (('A' << 24) | ('B' << 16) | ('C' << 8) | 'D')) throw new Exception("enumWithMacroTest 1 failed"); + if (enum_thorough_typesafe.enumWithMacroTest(enumWithMacro.ABCD2).swigValue != enum_thorough_typesafe.enumWithMacroTest(enumWithMacro.ABCD).swigValue) throw new Exception("enumWithMacroTest 2 failed"); + } // different types { if (enum_thorough_typesafe.differentTypesTest(DifferentTypes.typeint).swigValue != 10) throw new Exception("differentTypes 1 failed"); @@ -413,6 +417,8 @@ public class runme { if (enum_thorough_typesafe.differentTypesTest(DifferentTypes.typeboolfalse).swigValue != 0) throw new Exception("differentTypes 4 failed"); if (enum_thorough_typesafe.differentTypesTest(DifferentTypes.typechar).swigValue != (int)'C') throw new Exception("differentTypes 5 failed"); if (enum_thorough_typesafe.differentTypesTest(DifferentTypes.typedefaultint).swigValue != (int)'D') throw new Exception("differentTypes 6 failed"); + if (enum_thorough_typesafe.differentTypesTest(DifferentTypes.typecharcompound).swigValue != (int)'A' + 1) throw new Exception("differentTypes 7 failed"); + if (enum_thorough_typesafe.differentTypesTest(DifferentTypes.typecharcompound2).swigValue != (int)'B' << 2) throw new Exception("differentTypes 8 failed"); int global_enum = enum_thorough_typesafe.global_typeint; if (enum_thorough_typesafe.globalDifferentTypesTest(global_enum) != 10) throw new Exception("global differentTypes 1 failed"); @@ -426,6 +432,10 @@ public class runme { if (enum_thorough_typesafe.globalDifferentTypesTest(global_enum) != 'C') throw new Exception("global differentTypes 5 failed"); global_enum = enum_thorough_typesafe.global_typedefaultint; if (enum_thorough_typesafe.globalDifferentTypesTest(global_enum) != 'D') throw new Exception("global differentTypes 6 failed"); + global_enum = enum_thorough_typesafe.global_typecharcompound; + if (enum_thorough_typesafe.globalDifferentTypesTest(global_enum) != (int)'A' + 1) throw new Exception("global differentTypes 7 failed"); + global_enum = enum_thorough_typesafe.global_typecharcompound2; + if (enum_thorough_typesafe.globalDifferentTypesTest(global_enum) != (int)'B' << 2) throw new Exception("global differentTypes 8 failed"); } } } diff --git a/Examples/test-suite/csharp/li_boost_shared_ptr_director_runme.cs b/Examples/test-suite/csharp/li_boost_shared_ptr_director_runme.cs new file mode 100644 index 000000000..0a03b7f10 --- /dev/null +++ b/Examples/test-suite/csharp/li_boost_shared_ptr_director_runme.cs @@ -0,0 +1,111 @@ +using System; +using li_boost_shared_ptr_directorNamespace; + +public class li_boost_shared_ptr_director_runme { + + private static void check(int got, int expected) { + if (got != expected) + throw new Exception("Failed, got: " + got + " expected: " + expected); + } + + public static void Main() { + Derived a = new Derived(false); + Derived b = new Derived(true); + + check(li_boost_shared_ptr_director.call_ret_c_shared_ptr(a), 1); + check(li_boost_shared_ptr_director.call_ret_c_shared_ptr(b), -1); + check(li_boost_shared_ptr_director.call_ret_c_by_value(a), 1); + + check(li_boost_shared_ptr_director.call_ret_c_shared_ptr(a), 1); + check(li_boost_shared_ptr_director.call_ret_c_shared_ptr(b), -1); + check(li_boost_shared_ptr_director.call_ret_c_by_value(a), 1); + + check(li_boost_shared_ptr_director.call_take_c_by_value(a), 5); + check(li_boost_shared_ptr_director.call_take_c_by_ref(a), 6); + check(li_boost_shared_ptr_director.call_take_c_by_pointer(a), 7); + check(li_boost_shared_ptr_director.call_take_c_by_pointer_ref(a), 8); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_value(a), 9); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_ref(a), 10); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_pointer(a), 11); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_pointer_ref(a), 12); + + check(li_boost_shared_ptr_director.call_take_c_by_pointer_with_null(a), -2); + check(li_boost_shared_ptr_director.call_take_c_by_pointer_ref_with_null(a), -3); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_value_with_null(a), -4); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_ref_with_null(a), -5); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_pointer_with_null(a), -6); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_pointer_ref_with_null(a), -7); + } + +} + +class Derived : Base { + + private bool return_none; + + public Derived(bool flag) : base() { + this.return_none = flag; + } + + public override C ret_c_shared_ptr() { + if (this.return_none) + return null; + else + return new C(); + } + + public override C ret_c_by_value() { + return new C(); + } + + public override int take_c_by_value(C c) { + return c.get_m(); + } + + public override int take_c_by_ref(C c) { + return c.get_m(); + } + + public override int take_c_by_pointer(C c) { + if (c != null) + return c.get_m(); + else + return -2; + } + + public override int take_c_by_pointer_ref(C c) { + if (c != null) + return c.get_m(); + else + return -3; + } + + public override int take_c_shared_ptr_by_value(C c) { + if (c != null) + return c.get_m(); + else + return -4; + } + + public override int take_c_shared_ptr_by_ref(C c) { + if (c != null) + return c.get_m(); + else + return -5; + } + + public override int take_c_shared_ptr_by_pointer(C c) { + if (c != null) + return c.get_m(); + else + return -6; + } + + public override int take_c_shared_ptr_by_pointer_ref(C c) { + if (c != null) + return c.get_m(); + else + return -7; + } + +} diff --git a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs index 1f66042a6..863b86701 100644 --- a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs +++ b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs @@ -19,6 +19,13 @@ public class li_std_auto_ptr_runme { if (Klass.getTotal_count() != 2) throw new Exception("number of objects should be 2"); + using (Klass k3 = li_std_auto_ptr.makeKlassAutoPtr("second")) { + if (Klass.getTotal_count() != 3) + throw new Exception("number of objects should be 3"); + } + if (Klass.getTotal_count() != 2) + throw new Exception("number of objects should be 2"); + k1 = null; { int countdown = 500; diff --git a/Examples/test-suite/csharp/li_std_except_runme.cs b/Examples/test-suite/csharp/li_std_except_runme.cs index 86ab44892..c5ff26b6c 100644 --- a/Examples/test-suite/csharp/li_std_except_runme.cs +++ b/Examples/test-suite/csharp/li_std_except_runme.cs @@ -7,6 +7,7 @@ public class li_std_except_runme { public static void Main() { Test test = new Test(); + try { test.throw_bad_cast(); throw new Exception("throw_bad_cast failed"); } catch (InvalidCastException) {} try { test.throw_bad_exception(); throw new Exception("throw_bad_exception failed"); } catch (ApplicationException) {} try { test.throw_domain_error(); throw new Exception("throw_domain_error failed"); } catch (ApplicationException) {} try { test.throw_exception(); throw new Exception("throw_exception failed"); } catch (ApplicationException) {} diff --git a/Examples/test-suite/csharp/li_std_list_runme.cs b/Examples/test-suite/csharp/li_std_list_runme.cs new file mode 100644 index 000000000..1a5b1562d --- /dev/null +++ b/Examples/test-suite/csharp/li_std_list_runme.cs @@ -0,0 +1,402 @@ +using System; +using li_std_listNamespace; + +public class li_std_list_runme { + private static readonly int collectionSize = 20; + + public static void Main() { + // Setup a list of int + IntList list = new IntList(); + IntList.IntListNode node; + + for (int i = 0; i < 20; i++) { + int nb = i * 10; + list.Add(nb); + } + + // Count property test + if (list.Count != collectionSize) + throw new Exception("Count test failed"); + + // IsReadOnly property test + if (list.IsReadOnly) + throw new Exception("IsReadOnly test failed"); + + // Contains method test + if (!list.Contains(0)) + throw new Exception("Contains method test 1 failed"); + if (!list.Contains(2 * 10)) + throw new Exception("Contains method test 2 failed"); + if (!list.Contains(19 * 10)) + throw new Exception("Contains method test 3 failed"); + if (list.Contains(20 * 10)) + throw new Exception("Contains method test 4 failed"); + + // Nodes comparison method overload + { + IntList.IntListNode temp = new IntList.IntListNode(3); + if (list.First == temp) + throw new Exception("== overload method test (1) failed"); + temp = new IntList.IntListNode(0); + if (list.First == temp) + throw new Exception("== overload method test (2) failed"); + IntList.IntListNode temp2 = new IntList.IntListNode(0); + if (temp == temp2) + throw new Exception("== overload method test (3) failed"); + if (!(list.First == list.First)) + throw new Exception("== overload method test (4) failed"); + if (list.First != list.First) + throw new Exception("!= overload method test (1) failed"); + if (!(temp != temp2)) + throw new Exception("!= overload method test (2) failed"); + if (list.First.Equals(temp)) + throw new Exception("Equals method test failed"); + if (list.First.GetHashCode() == temp.GetHashCode()) + throw new Exception("GetHashCode method test (1) failed"); + if (list.First.GetHashCode() == list.First.GetHashCode()) + throw new Exception("GetHashCode method test (2) failed"); + + } + + // Getter test + { + if (list.First == null) + throw new Exception("First getter test (1) failed"); + if (list.Last == null) + throw new Exception("Last getter test (1) failed"); + if (list.Last.Next != null) + throw new Exception("Next getter test (1) failed"); + if (list.First.Next == null) + throw new Exception("Next getter test (2) failed"); + if (list.First.Previous != null) + throw new Exception("Previous getter test (1) failed"); + if (list.Last.Previous == null) + throw new Exception("Previous getter test (2) failed"); + } + + // AddFirst method test + node = list.AddFirst(34); + if (list.First.Value != 34 || node.Value != 34 || node != list.First) + throw new Exception("AddFirst method test failed"); + try { + list.AddFirst(null); + } catch (ArgumentNullException) { + try { + list.AddFirst(list.First); + } catch (InvalidOperationException) { + } + } + + // RemoveFirst method test + int tmp = list.First.Value; + list.RemoveFirst(); + if (list.First.Value == tmp || list.First.Value != 0 * 10) + throw new Exception("RemoveFirst method test failed"); + + // AddLast method test + node = list.AddLast(8); + if (list.Last.Value != 8 || node.Value != 8 || node != list.Last) + throw new Exception("AddLast method test failed"); + try { + list.AddLast(null); + } catch (ArgumentNullException) { + try { + list.AddLast(list.First); + } catch (InvalidOperationException) { + } + } + + // RemoveLast method test + int tmp2 = list.Last.Value; + list.RemoveLast(); + if (list.Last.Value == tmp2 || list.Last.Value != (list.Count - 1) * 10) + throw new Exception("RemoveLast method test failed"); + + // AddBefore method test + node = list.AddBefore(list.Last, 17); + if (list.Last.Previous.Value != 17 || node.Value != 17 || node != list.Last.Previous) + throw new Exception("AddBefore method test (1) failed"); + try { + node = null; + list.AddBefore(list.Last, node); + throw new Exception("AddBefore method test (2) failed"); + } catch (ArgumentNullException) { + try { + node = new IntList.IntListNode(1); + list.AddBefore(null, node); + throw new Exception("AddBefore method test (3) failed"); + } catch (ArgumentNullException) { + try { + list.AddBefore(list.Last, list.First); + } catch (InvalidOperationException) { + } + } + } + + // AddAfter method test + node = list.AddAfter(list.First, 47); + if (list.First.Next.Value != 47 || node.Value != 47 || node != list.First.Next) + throw new Exception("AddAfter method test (1) failed"); + try { + node = null; + list.AddAfter(list.First.Next, node); + throw new Exception("AddAfter method test (2) failed"); + } catch (ArgumentNullException) { + try { + list.AddAfter(list.First, list.Last); + } catch (InvalidOperationException) { + } + } + + // Find method test + node = list.Find(0); + if (node == null || node.Value != 0) + throw new Exception("Find method test (1) failed"); + node = list.Find(47); + if (node == null || node.Value != 47) + throw new Exception("Find method test (2) failed"); + node = list.Find(190); + if (node == null || node.Value != 190) + throw new Exception("Find method test (3) failed"); + node = list.Find(-3); + if (node != null) + throw new Exception("Find method test (4) failed"); + + // Remove method test + if (!list.Remove(17) || list.Contains(17) || list.Last.Previous.Value == 17) + throw new Exception("Remove method test (1) failed"); + if (!list.Remove(47) || list.Contains(47) || list.First.Next.Value == 47) + throw new Exception("Remove method test (2) failed"); + if (!list.Remove(0) || list.Contains(0) || list.First.Value == 0) + throw new Exception("Remove method test (3) failed"); + if (!list.Remove(190) || list.Contains(190) || list.Last.Value == 190) + throw new Exception("Remove method test (4) failed"); + try { + node = null; + list.Remove(node); + throw new Exception("Remove method test (5) failed"); + } catch (ArgumentNullException) { + try { + node = new IntList.IntListNode(4); + list.Remove(node); + throw new Exception("Remove method test (5) failed"); + } catch (InvalidOperationException) { + } + } + + // ICollection constructor test + { + int[] intArray = new int[] { 0, 11, 22, 33, 44, 55, 33 }; + IntList il = new IntList(intArray); + if (intArray.Length != il.Count) + throw new Exception("ICollection constructor length check failed: " + intArray.Length + "-" + il.Count); + node = il.First; + for (int i = 0; i < intArray.Length; i++) { + if (intArray[i] != node.Value) + throw new Exception("ICollection constructor failed, index:" + i); + node = node.Next; + } + try { + new IntList((System.Collections.ICollection)null); + throw new Exception("ICollection constructor null test failed"); + } catch (ArgumentNullException) { + } + } + + // Enumerator test + { + node = list.First; + System.Collections.IEnumerator myEnumerator = list.GetEnumerator(); + while (myEnumerator.MoveNext()) { + if ((int)myEnumerator.Current != node.Value) + throw new Exception("Enumerator (1) test failed"); + node = node.Next; + } + } + { + node = list.First; + System.Collections.Generic.IEnumerator myEnumerator = list.GetEnumerator(); + while (myEnumerator.MoveNext()) { + if (myEnumerator.Current != node.Value) + throw new Exception("Enumerator (2) test failed"); + node = node.Next; + } + } + { + node = list.First; + IntList.IntListEnumerator myEnumerator = list.GetEnumerator(); + while (myEnumerator.MoveNext()) { + if (myEnumerator.Current != node.Value) + throw new Exception("Enumerator (3) test failed"); + node = node.Next; + } + } + { + node = list.First; + foreach (var elem in list) { + if (elem != node.Value) + throw new Exception("Enumerator (4) test failed"); + node = node.Next; + } + } + + // CopyTo method test + { + int[] outputarray = new int[collectionSize - 2]; + list.CopyTo(outputarray, 0); + int index = 0; + IntList.IntListNode temp = list.First; + foreach (int val in outputarray) { + if (temp.Value != val) { + throw new Exception("CopyTo method test (1) failed, index:" + index); + } + index++; + temp = temp.Next; + } + } + { + DoubleList inputlist = new DoubleList(); + int arrayLen = 10; + for (int i = 0; i < arrayLen; i++) { + double num = i * 10.1; + inputlist.Add(num); + } + double[] outputarray = new double[arrayLen]; + inputlist.CopyTo(outputarray, 0); + DoubleList.DoubleListNode temp = inputlist.First; + for (int i = 0; i < arrayLen; i++) { + if (outputarray[i] != temp.Value) + throw new Exception("CopyTo method test (2) failed, index:" + i); + temp = temp.Next; + } + } + { + StructList inputlist = new StructList(); + int arrayLen = 10; + for (int i = 0; i < arrayLen; i++) + inputlist.Add(new Struct(i / 10.0)); + Struct[] outputarray = new Struct[arrayLen]; + inputlist.CopyTo(outputarray, 0); + StructList.StructListNode temp = inputlist.First; + for (int i = 0; i < arrayLen; i++) { + if (outputarray[i].num != temp.Value.num) + throw new Exception("CopyTo method test (3) failed, index:" + i); + temp = temp.Next; + } + foreach (Struct s in inputlist) { + s.num += 20.0; + } + temp = inputlist.First; + for (int i = 0; i < arrayLen; i++) { + if (outputarray[i].num != temp.Value.num) + throw new Exception("CopyTo method test (4) failed, index:" + i); + temp = temp.Next; + } + } + try { + list.CopyTo(null, 0); + throw new Exception("CopyTo method test (5) failed"); + } catch (ArgumentNullException) { + } + + // Clear() test + list.Clear(); + if (list.Count != 0) + throw new Exception("Clear method failed"); + + // Finally test the methods being wrapped + { + IntList il = new IntList(); + for (int i = 0; i < 4; i++) { + il.Add(i); + } + + double x = li_std_list.average(il); + x += li_std_list.average(new IntList(new int[] { 1, 2, 3, 4 })); + + DoubleList dlist = new DoubleList(); + for (int i = 0; i < 10; i++) { + dlist.Add(i / 2.0); + } + li_std_list.halve_in_place(dlist); + } + + // Dispose() + { + using (StructList ls = new StructList(new Struct[] { new Struct(0.0), new Struct(11.1) })) + using (DoubleList ld = new DoubleList(new double[] { 0.0, 11.1 })) { } + } + + // More wrapped methods + { + FloatList l0 = li_std_list.listreal(new FloatList()); + float flo = 123.456f; + l0.Add(flo); + flo = l0.First.Value; + + IntList l1 = li_std_list.listint(new IntList()); + IntPtrList l2 = li_std_list.listintptr(new IntPtrList()); + IntConstPtrList l3 = li_std_list.listintconstptr(new IntConstPtrList()); + + l1.Add(123); + l2.Clear(); + l3.Clear(); + + StructList l4 = li_std_list.liststruct(new StructList()); + StructPtrList l5 = li_std_list.liststructptr(new StructPtrList()); + StructConstPtrList l6 = li_std_list.liststructconstptr(new StructConstPtrList()); + + l4.Add(new Struct(123)); + l5.Add(new Struct(123)); + l6.Add(new Struct(123)); + } + + // Test lists of pointers + { + StructPtrList inputlist = new StructPtrList(); + int arrayLen = 10; + for (int i = 0; i < arrayLen; i++) { + inputlist.Add(new Struct(i / 10.0)); + } + Struct[] outputarray = new Struct[arrayLen]; + inputlist.CopyTo(outputarray, 0); + StructPtrList.StructPtrListNode temp = inputlist.First; + for (int i = 0; i < arrayLen; i++) { + if (outputarray[i].num != temp.Value.num) + throw new Exception("StructPtrList test (1) failed, i:" + i); + temp = temp.Next; + } + foreach (Struct s in inputlist) { + s.num += 20.0; + } + for (int i = 0; i < arrayLen; i++) { + if (outputarray[i].num != 20.0 + i / 10.0) + throw new Exception("StructPtrList test (2) failed (a deep copy was incorrectly made), i:" + i); + } + } + + // Test lists of const pointers + { + StructConstPtrList inputlist = new StructConstPtrList(); + int arrayLen = 10; + for (int i = 0; i < arrayLen; i++) { + inputlist.Add(new Struct(i / 10.0)); + } + Struct[] outputarray = new Struct[arrayLen]; + inputlist.CopyTo(outputarray, 0); + StructConstPtrList.StructConstPtrListNode temp = inputlist.First; + for (int i = 0; i < arrayLen; i++) { + if (outputarray[i].num != temp.Value.num) + throw new Exception("StructConstPtrList test (1) failed, i:" + i); + temp = temp.Next; + } + foreach (Struct s in inputlist) { + s.num += 20.0; + } + for (int i = 0; i < arrayLen; i++) { + if (outputarray[i].num != 20.0 + i / 10.0) + throw new Exception("StructConstPtrList test (2) failed (a deep copy was incorrectly made), i:" + i); + } + } + } +} diff --git a/Examples/test-suite/csharp/li_std_map_runme.cs b/Examples/test-suite/csharp/li_std_map_runme.cs index 0fe1ab5cd..51510c9fc 100644 --- a/Examples/test-suite/csharp/li_std_map_runme.cs +++ b/Examples/test-suite/csharp/li_std_map_runme.cs @@ -18,7 +18,7 @@ public class li_std_map_runme { public static void Main() { - // Set up an int int map + // Set up an string to int map StringIntMap simap = new StringIntMap(); for (int i = 0; i < collectionSize; i++) { @@ -240,6 +240,20 @@ public class li_std_map_runme { throw new Exception("Key test (2) on complex key map failed"); } + // Custom compare function + { + StringLengthNumberMap slmap = new StringLengthNumberMap(); + li_std_map.populate(slmap); + + string keys = string.Join(" ", new List(slmap.Keys)); + if (keys != "a aa zzz xxxx aaaaa") + throw new Exception("Keys are wrong or in wrong order: " + keys); + + string values = string.Join(" ", new List(slmap.Values)); + if (values != "1 2 3 4 5") + throw new Exception("Values are wrong or in wrong order: " + values); + } + // All done } } diff --git a/Examples/test-suite/csharp/li_std_set_runme.cs b/Examples/test-suite/csharp/li_std_set_runme.cs new file mode 100644 index 000000000..e9cd2c271 --- /dev/null +++ b/Examples/test-suite/csharp/li_std_set_runme.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using li_std_setNamespace; + +public class runme +{ + static void checkThat(bool mustBeTrue, string message) + { + if (!mustBeTrue) + throw new Exception("Test that the set " + message + " failed"); + } + + static void Main() + { + StringSet ss = new StringSet(); + + // Check the interface methods first. + ISet s = ss; + + checkThat(s.Count == 0, "is initially empty"); + checkThat(!s.Contains("key"), "doesn't contain inexistent element"); + checkThat(!s.Remove("key"), "returns false when removing inexistent element"); + + checkThat(s.Add("key"), "returns true when adding a new element"); + checkThat(!s.Add("key"), "returns false when adding an existing element"); + checkThat(s.Contains("key"), "contains the just added element"); + checkThat(s.Remove("key"), "returns true when removing an existing element"); + checkThat(s.Count == 0, "is empty again"); + + checkThat(s.Add("key1"), "Add(key1) returns true"); + checkThat(s.Add("key2"), "Add(key2) returns true"); + checkThat(s.Add("key3"), "Add(key3) returns true"); + + // Also check a different interface, providing a different Add() (sic!). + ICollection coll = ss; + coll.Add("key"); + checkThat(ss.Count == 4, "contains 4 elements"); + + // Now use object-specific methods, mimicking HashSet<>. + string val; + checkThat(ss.TryGetValue("key1", out val), "could retrieve existing item"); + checkThat(val.Equals("key1"), "value was returned correctly by TryGetValue()"); + checkThat(!ss.TryGetValue("no-such-key", out val), "couldn't retrieve inexistent item"); + checkThat(val == null, "value was reset after failed TryGetValue()"); + + IList list = new List(); + foreach (string str in ss) { + list.Add(str); + } + checkThat(list.Count == 4, "copy contains 4 elements"); + + ss.Clear(); + checkThat(ss.Count == 0, "is empty after Clear()"); + + // Check set-theoretic methods. + checkThat(new StringSet().SetEquals(new StringSet()), "SetEquals() works for empty sets"); + checkThat(new StringSet{"foo"}.SetEquals(new StringSet{"foo"}), "SetEquals() works for non-empty sets"); + checkThat(!new StringSet{"foo"}.SetEquals(new[] {"bar"}), "SetEquals() doesn't always return true"); + + ss = new StringSet{"foo", "bar", "baz"}; + ss.ExceptWith(new[] {"baz", "quux"}); + checkThat(ss.SetEquals(new[] {"foo", "bar"}), "ExceptWith works"); + + ss = new StringSet{"foo", "bar", "baz"}; + ss.IntersectWith(new[] {"baz", "quux"}); + checkThat(ss.SetEquals(new[] {"baz"}), "IntersectWith works"); + + checkThat(ss.IsProperSubsetOf(new[] {"bar", "baz"}), "IsProperSubsetOf works"); + checkThat(!ss.IsProperSubsetOf(new[] {"baz"}), "!IsProperSubsetOf works"); + checkThat(ss.IsSubsetOf(new[] {"bar", "baz"}), "IsSubsetOf works"); + checkThat(!ss.IsSubsetOf(new[] {"bar"}), "!IsSubsetOf works"); + + ss = new StringSet{"foo", "bar", "baz"}; + checkThat(ss.IsProperSupersetOf(new[] {"bar"}), "IsProperSupersetOf works"); + checkThat(!ss.IsProperSupersetOf(new[] {"quux"}), "IsProperSupersetOf works"); + checkThat(ss.IsSupersetOf(new[] {"foo", "bar", "baz"}), "IsProperSupersetOf works"); + checkThat(!ss.IsSupersetOf(new[] {"foo", "bar", "baz", "quux"}), "IsProperSupersetOf works"); + + checkThat(ss.Overlaps(new[] {"foo"}), "Overlaps works"); + checkThat(!ss.Overlaps(new[] {"moo"}), "!Overlaps works"); + + ss.SymmetricExceptWith(new[] {"baz", "quux"}); + checkThat(ss.SetEquals(new[] {"foo", "bar", "quux"}), "SymmetricExceptWith works"); + + ss = new StringSet{"foo", "bar", "baz"}; + ss.UnionWith(new[] {"baz", "quux"}); + checkThat(ss.SetEquals(new[] {"foo", "bar", "baz", "quux"}), "UnionWith works"); + + // Check a set of another type. + FooSet fooSet = new FooSet(); + ISet fooISet = fooSet; + checkThat(fooISet.Count == 0, "is initially empty"); + checkThat(fooISet.Add(new Foo(17)), "added successfully"); + checkThat(fooISet.Count == 1, "is not empty any more"); + + // And a set of primitive type. + IntSet intSet = new IntSet(); + checkThat(intSet.Count == 0, "is initially empty"); + checkThat(intSet.Add(17), "17 added successfully"); + checkThat(!intSet.Add(17), "17 not added again"); + checkThat(intSet.Count == 1, "not empty any more"); + checkThat(intSet.Add(289), "289 added successfully"); + checkThat(intSet.Count == 2, "even less empty now"); + } +} diff --git a/Examples/test-suite/csharp/li_std_vector_runme.cs b/Examples/test-suite/csharp/li_std_vector_runme.cs index fa8700d89..0c6211ca5 100644 --- a/Examples/test-suite/csharp/li_std_vector_runme.cs +++ b/Examples/test-suite/csharp/li_std_vector_runme.cs @@ -121,7 +121,7 @@ public class li_std_vector_runme { throw new Exception("Contains test 4 failed"); { - // ICollection constructor + // IEnumerable constructor double[] doubleArray = new double[] { 0.0, 11.1, 22.2, 33.3, 44.4, 55.5, 33.3 }; DoubleVector dv = new DoubleVector(doubleArray); if (doubleArray.Length != dv.Count) @@ -177,6 +177,17 @@ public class li_std_vector_runme { if (doubleArray[i] != dvCopy[i]) throw new Exception("Copy constructor failed, index:" + i); } + if (dvCopy.Count != doubleArray.Length) + throw new Exception("Copy constructor lengths mismatch"); + + // ToArray test + double[] dvArray = dv.ToArray(); + for (int i=0; i + { + global::System.Collections.Generic.IEnumerable collection = one_two_three; + check123(new StringVector(collection)); + } + + // Test construction from IList<> + { + global::System.Collections.Generic.IList collection = one_two_three; + check123(new StringVector(collection)); + } + + // Test construction from ICollection + { + global::System.Collections.ICollection collection = one_two_three; + check123(new StringVector(collection)); + } + + // Test construction from ICollection<> + { + global::System.Collections.Generic.ICollection collection = new global::System.Collections.Generic.List(one_two_three); + check123(new StringVector(collection)); + } + } + + } + + private static void check123(StringVector stringv) { + string concatenated = ""; + foreach (string s in stringv) + concatenated = concatenated + s; + if (concatenated != "onetwothree") + throw new Exception("concatenated string failed: " + concatenated); } } diff --git a/Examples/test-suite/csharp/li_std_wstring_runme.cs b/Examples/test-suite/csharp/li_std_wstring_runme.cs index fe663a3e0..ab013f923 100644 --- a/Examples/test-suite/csharp/li_std_wstring_runme.cs +++ b/Examples/test-suite/csharp/li_std_wstring_runme.cs @@ -3,74 +3,113 @@ using li_std_wstringNamespace; public class runme { + static private void check_equal(char a, char b) + { + if (a != b) + throw new Exception("char failed '" + a + "' != '" + b + "'"); + } + + static private void check_equal(string a, string b) + { + if (a != b) + throw new Exception("string failed '" + a + "' != '" + b + "'"); + } + static void Main() { - char y='h'; + char h = 'h'; + check_equal(li_std_wstring.test_wcvalue(h), h); - if (li_std_wstring.test_wcvalue(y) != y) - throw new Exception("bad string mapping:" + li_std_wstring.test_wcvalue(y)); + string x = "abc"; + check_equal(li_std_wstring.test_ccvalue(x), x); + check_equal(li_std_wstring.test_cvalue(x), x); - if (li_std_wstring.test_wcvalue_w() != 'W') - throw new Exception("bad string mapping:" + li_std_wstring.test_wcvalue_w()); + check_equal(li_std_wstring.test_wchar_overload(x), x); + check_equal(li_std_wstring.test_wchar_overload(), null); - string x="hello"; + li_std_wstring.test_pointer(null); + li_std_wstring.test_const_pointer(null); - if (li_std_wstring.test_ccvalue(x) != x) - throw new Exception("bad string mapping"); + try { + li_std_wstring.test_value(null); + throw new Exception("NULL check failed"); + } catch (ArgumentNullException) { + } - if (li_std_wstring.test_cvalue(x) != x) - throw new Exception("bad string mapping"); + try { + li_std_wstring.test_reference(null); + throw new Exception("NULL check failed"); + } catch (ArgumentNullException e) { + if (!e.Message.Contains("type is null")) + throw new Exception("Missing text " + e); + } + try { + li_std_wstring.test_const_reference(null); + throw new Exception("NULL check failed"); + } catch (ArgumentNullException e) { + if (!e.Message.Contains("null wstring")) + throw new Exception("Missing text " + e); + } + x = "hello"; + check_equal(li_std_wstring.test_const_reference(x), x); - if (li_std_wstring.test_value(x) != x) - throw new Exception("bad string mapping: " + x + li_std_wstring.test_value(x)); + /* Postpone, tricky, std::wstring portability problem. + * std::wstring is 2 bytes on Windows, 4 bytes on Linux, LPWSTR is 2 bytes. + * .NET marshalling should work on Windows but not Linux. + string s = "abc"; + if (!li_std_wstring.test_equal_abc(s)) + throw new Exception("Not equal " + s); + */ - if (li_std_wstring.test_const_reference(x) != x) - throw new Exception("bad string mapping"); + try { + li_std_wstring.test_throw(); + } catch (Exception e) { + check_equal(e.Message, "throwing test_throw"); + } + x = "abc\0def"; + // Unlike other languages, embedded NULL in std::string not supported + // check_equal(li_std_wstring.test_value(x), x); + check_equal(li_std_wstring.test_value(x), "abc"); + check_equal(li_std_wstring.test_ccvalue(x), "abc"); + check_equal(li_std_wstring.test_wchar_overload(x), "abc"); - string s = "he"; - s = s + "llo"; + { + // Unicode strings + string[] test_strings = { + "JP: 日本語", "DE: Kröpeliner StraĂźe" , "RU: Война и мир", "EN: War and Peace" + }; - if (s != x) - throw new Exception("bad string mapping: " + s + x); + foreach (string expected in test_strings) + { + string received = li_std_wstring.test_value(expected); + check_equal(received, expected); + } - if (li_std_wstring.test_value(s) != x) - throw new Exception("bad string mapping"); + foreach (string expected in test_strings) + { + string received = li_std_wstring.test_const_reference(expected); + check_equal(received, expected); + } - if (li_std_wstring.test_const_reference(s) != x) - throw new Exception("bad string mapping"); + foreach (string expected in test_strings) + { + string received = li_std_wstring.test_ccvalue(expected); + check_equal(received, expected); + } - string a = s; - - if (li_std_wstring.test_value(a) != x) - throw new Exception("bad string mapping"); - - if (li_std_wstring.test_const_reference(a) != x) - throw new Exception("bad string mapping"); - - string b = " world"; - - if (a + b != "hello world") - throw new Exception("bad string mapping"); - - if (a + " world" != "hello world") - throw new Exception("bad string mapping"); - - if ("hello" + b != "hello world") - throw new Exception("bad string mapping"); - - s = "hello world"; - - B myB = new B("hi"); - - myB.name = "hello"; - if (myB.name != "hello") - throw new Exception("bad string mapping"); - - myB.a = "hello"; - if (myB.a != "hello") - throw new Exception("bad string mapping"); + /* Not working on Windows okay on Linux + foreach (string test_string in test_strings) + { + foreach (char expected in test_string) + { + char received = li_std_wstring.test_wcvalue(expected); + check_equal(received, expected); + } + } + */ + } } } diff --git a/Examples/test-suite/csharp/nested_in_template_runme.cs b/Examples/test-suite/csharp/nested_in_template_runme.cs new file mode 100644 index 000000000..e57e03999 --- /dev/null +++ b/Examples/test-suite/csharp/nested_in_template_runme.cs @@ -0,0 +1,10 @@ +using System; +using nested_in_templateNamespace; + +public class runme { + static void Main() { + var cd = new OuterTemplate1.ConcreteDerived(88); + if (cd.m_value != 88) + throw new Exception("ConcreteDerived not created correctly"); + } +} diff --git a/Examples/test-suite/csharp/nested_inheritance_interface_runme.cs b/Examples/test-suite/csharp/nested_inheritance_interface_runme.cs new file mode 100644 index 000000000..810b7db6d --- /dev/null +++ b/Examples/test-suite/csharp/nested_inheritance_interface_runme.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using nested_inheritance_interfaceNamespace; + +public class nested_inheritance_interface_runme { + + static string SortArrayToString(string[] types) { + Array.Sort(types); + return string.Join(" ", types); + } + + static string SortArrayToString(Type[] types) { + List stypes = new List(); + foreach (Type t in types) + stypes.Add(t.Name); + return SortArrayToString(stypes.ToArray()); + } + + private static void takeIA(IASwigInterface ia) { + } + + public static void Main() { + Type[] BNInterfaces = typeof(B.N).GetInterfaces(); + string expectedInterfacesString = "IASwigInterface IDisposable"; + string actualInterfacesString = SortArrayToString(BNInterfaces); + if (expectedInterfacesString != actualInterfacesString) + throw new Exception("Expected interfaces for " + typeof(B.N).Name + ": \n" + expectedInterfacesString + "\n" + "Actual interfaces: \n" + actualInterfacesString); + + if (!typeof(IASwigInterface).IsInterface) + throw new Exception(typeof(IASwigInterface).Name + " should be an interface but is not"); + + // overloaded methods check + B.N d = new B.N(); + takeIA(d); + } +} diff --git a/Examples/test-suite/csharp/preproc_constants_c_runme.cs b/Examples/test-suite/csharp/preproc_constants_c_runme.cs index 76c684d85..5966d5266 100644 --- a/Examples/test-suite/csharp/preproc_constants_c_runme.cs +++ b/Examples/test-suite/csharp/preproc_constants_c_runme.cs @@ -36,7 +36,7 @@ public class runme { assert( typeof(string) == preproc_constants_c.CONST_STRING2.GetType() ); assert( typeof(int) == preproc_constants_c.INT_AND_BOOL.GetType() ); -// assert( typeof(int) == preproc_constants_c.INT_AND_CHAR.GetType() ); + assert( typeof(int) == preproc_constants_c.INT_AND_CHAR.GetType() ); assert( typeof(int) == preproc_constants_c.INT_AND_INT.GetType() ); assert( typeof(uint) == preproc_constants_c.INT_AND_UINT.GetType() ); assert( typeof(int) == preproc_constants_c.INT_AND_LONG.GetType() ); @@ -61,7 +61,9 @@ public class runme { assert( typeof(int) == preproc_constants_c.EXPR_LAND.GetType() ); assert( typeof(int) == preproc_constants_c.EXPR_LOR.GetType() ); assert( typeof(double) == preproc_constants_c.EXPR_CONDITIONAL.GetType() ); - + assert( typeof(double) == preproc_constants_c.EXPR_MIXED1.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_WCHAR_MAX.GetType() ); + assert( typeof(int) == preproc_constants_c.EXPR_WCHAR_MIN.GetType() ); } static void assert(bool assertion) { if (!assertion) diff --git a/Examples/test-suite/csharp/preproc_constants_runme.cs b/Examples/test-suite/csharp/preproc_constants_runme.cs index 9fae5914a..6af8f20a4 100644 --- a/Examples/test-suite/csharp/preproc_constants_runme.cs +++ b/Examples/test-suite/csharp/preproc_constants_runme.cs @@ -35,7 +35,7 @@ public class runme { assert( typeof(string) == preproc_constants.CONST_STRING2.GetType() ); assert( typeof(int) == preproc_constants.INT_AND_BOOL.GetType() ); -// assert( typeof(int) == preproc_constants.INT_AND_CHAR.GetType() ); + assert( typeof(int) == preproc_constants.INT_AND_CHAR.GetType() ); assert( typeof(int) == preproc_constants.INT_AND_INT.GetType() ); assert( typeof(uint) == preproc_constants.INT_AND_UINT.GetType() ); assert( typeof(int) == preproc_constants.INT_AND_LONG.GetType() ); @@ -60,6 +60,9 @@ public class runme { assert( typeof(bool) == preproc_constants.EXPR_LAND.GetType() ); assert( typeof(bool) == preproc_constants.EXPR_LOR.GetType() ); assert( typeof(double) == preproc_constants.EXPR_CONDITIONAL.GetType() ); + assert( typeof(double) == preproc_constants.EXPR_MIXED1.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_WCHAR_MAX.GetType() ); + assert( typeof(int) == preproc_constants.EXPR_WCHAR_MIN.GetType() ); } static void assert(bool assertion) { diff --git a/Examples/test-suite/csharp/proxycode_runme.cs b/Examples/test-suite/csharp/proxycode_runme.cs new file mode 100644 index 000000000..24e76c0c6 --- /dev/null +++ b/Examples/test-suite/csharp/proxycode_runme.cs @@ -0,0 +1,33 @@ +using System; +using proxycodeNamespace; + +public class proxycode_runme { + + public static void Main() { + if (new Proxy1().proxycode1(100) != 101) + throw new Exception("Fail"); + if (new Proxy2().proxycode2a(100) != 102) + throw new Exception("Fail"); + if (new Proxy2().proxycode2b(100) != 102) + throw new Exception("Fail"); + if (new Proxy3().proxycode3(100) != 103) + throw new Exception("Fail"); + + if (new Proxy4().proxycode4(100) != 104) + throw new Exception("Fail"); + if (new Proxy4.Proxy4Nested().proxycode4nested(100) != 144) + throw new Exception("Fail"); + + if (new Proxy5a().proxycode5((short)100) != (short)100) + throw new Exception("Fail"); + if (new Proxy5b().proxycode5(100) != 100) + throw new Exception("Fail"); + if (new Proxy5b().proxycode5(100, 100) != 255) + throw new Exception("Fail"); + + uint t1 = 10; + uint t2 = 100; + Proxy6 p = new Proxy6().proxyUseT(t1, t2); + p.useT(t1, t2); + } +} diff --git a/Examples/test-suite/csharp_exceptions.i b/Examples/test-suite/csharp_exceptions.i index e5b4d495b..71581480e 100644 --- a/Examples/test-suite/csharp_exceptions.i +++ b/Examples/test-suite/csharp_exceptions.i @@ -1,5 +1,11 @@ %module csharp_exceptions +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) +%{ +#define TESTCASE_THROW1(T1) +%} + %include %inline %{ @@ -36,21 +42,16 @@ } %inline %{ - -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - // %exception tests void ThrowByValue() { throw Ex("ThrowByValue"); } void ThrowByReference() { throw Ex("ThrowByReference"); } // %csnothrowexception void NoThrowException() { throw Ex("NoThrowException"); } // exception specifications -void ExceptionSpecificationValue() throw(Ex) { throw Ex("ExceptionSpecificationValue"); } -void ExceptionSpecificationReference() throw(Ex&) { throw Ex("ExceptionSpecificationReference"); } -void ExceptionSpecificationString() throw(const char *) { throw "ExceptionSpecificationString"; } -void ExceptionSpecificationInteger() throw(int) { throw 20; } +void ExceptionSpecificationValue() TESTCASE_THROW1(Ex) { throw Ex("ExceptionSpecificationValue"); } +void ExceptionSpecificationReference() TESTCASE_THROW1(Ex&) { throw Ex("ExceptionSpecificationReference"); } +void ExceptionSpecificationString() TESTCASE_THROW1(const char *) { throw "ExceptionSpecificationString"; } +void ExceptionSpecificationInteger() TESTCASE_THROW1(int) { throw 20; } %} // test exceptions in the default typemaps @@ -64,15 +65,15 @@ void NullValue(Ex e) {} // enums %inline %{ enum TestEnum {TestEnumItem}; -void ExceptionSpecificationEnumValue() throw(TestEnum) { throw TestEnumItem; } -void ExceptionSpecificationEnumReference() throw(TestEnum&) { throw TestEnumItem; } +void ExceptionSpecificationEnumValue() TESTCASE_THROW1(TestEnum) { throw TestEnumItem; } +void ExceptionSpecificationEnumReference() TESTCASE_THROW1(TestEnum&) { throw TestEnumItem; } %} // std::string %include %inline %{ -void ExceptionSpecificationStdStringValue() throw(std::string) { throw std::string("ExceptionSpecificationStdStringValue"); } -void ExceptionSpecificationStdStringReference() throw(const std::string&) { throw std::string("ExceptionSpecificationStdStringReference"); } +void ExceptionSpecificationStdStringValue() TESTCASE_THROW1(std::string) { throw std::string("ExceptionSpecificationStdStringValue"); } +void ExceptionSpecificationStdStringReference() TESTCASE_THROW1(const std::string&) { throw std::string("ExceptionSpecificationStdStringReference"); } void NullStdStringValue(std::string s) {} void NullStdStringReference(std::string &s) {} %} @@ -104,12 +105,8 @@ void MemoryLeakCheck() { %inline %{ struct constructor { constructor(std::string s) {} - constructor() throw(int) { throw 10; } + constructor() TESTCASE_THROW1(int) { throw 10; } }; - -#if defined(_MSC_VER) - #pragma warning(default: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif %} // test exception pending in the csout typemaps @@ -239,3 +236,4 @@ struct ThrowsClass { %inline %{ void InnerExceptionTest() { throw Ex("My InnerException message"); } %} + diff --git a/Examples/test-suite/csharp_lib_arrays_bool.i b/Examples/test-suite/csharp_lib_arrays_bool.i new file mode 100644 index 000000000..58cee9d80 --- /dev/null +++ b/Examples/test-suite/csharp_lib_arrays_bool.i @@ -0,0 +1,78 @@ +%module csharp_lib_arrays_bool + +%include "arrays_csharp.i" + +%apply bool INPUT[] { bool* sourceArray } +%apply bool OUTPUT[] { bool* targetArray } + +%apply bool INOUT[] { bool* array1 } +%apply bool INOUT[] { bool* array2 } + +%inline %{ +#include + +/* copy the contents of the first array to the second */ +void myArrayCopyBool( bool* sourceArray, bool* targetArray, int nitems ) { + int i; + for ( i = 0; i < nitems; i++ ) { + targetArray[ i ] = sourceArray[ i ]; + } +} + +/* swap the contents of the two arrays */ +void myArraySwapBool( bool* array1, bool* array2, int nitems ) { + int i; + bool temp; + for ( i = 0; i < nitems; i++ ) { + temp = array1[ i ]; + array1[ i ] = array2[ i ]; + array2[ i ] = temp; + } +} + +bool checkBoolArrayCorrect( bool* sourceArray, int sourceArraySize ) { + if( sourceArraySize != 8 ) { + std::cout << "checkBoolArrayCorrect: Expected array with 8 elements" << std::endl; + return false; + } + return sourceArray[0] == true && + sourceArray[1] == false && + sourceArray[2] == false && + sourceArray[3] == true && + sourceArray[4] == false && + sourceArray[5] == true && + sourceArray[6] == true && + sourceArray[7] == false; +} +%} + +%clear bool* sourceArray; +%clear bool* targetArray; + +%clear bool* array1; +%clear bool* array2; + +// Below replicates the above array handling but this time using the pinned (fixed) array typemaps +%csmethodmodifiers myArrayCopyUsingFixedArraysBool "public unsafe"; +%csmethodmodifiers myArraySwapUsingFixedArraysBool "public unsafe"; + +%apply bool FIXED[] { bool* sourceArray } +%apply bool FIXED[] { bool* targetArray } + +%inline %{ +void myArrayCopyUsingFixedArraysBool( bool *sourceArray, bool* targetArray, int nitems ) { + myArrayCopyBool(sourceArray, targetArray, nitems); +} +%} + +%apply bool FIXED[] { bool* array1 } +%apply bool FIXED[] { bool* array2 } + +%inline %{ +void myArraySwapUsingFixedArraysBool( bool* array1, bool* array2, int nitems ) { + myArraySwapBool(array1, array2, nitems); +} +%} + + + diff --git a/Examples/test-suite/d/Makefile.in b/Examples/test-suite/d/Makefile.in index 3333df110..a20cfb4e3 100644 --- a/Examples/test-suite/d/Makefile.in +++ b/Examples/test-suite/d/Makefile.in @@ -24,6 +24,12 @@ CPP_TEST_CASES = \ d_nativepointers \ exception_partial_info +CPP11_TEST_CASES = \ + cpp11_shared_ptr_const \ + cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ + cpp11_shared_ptr_upcast \ + include $(srcdir)/../common.mk # Overridden variables here diff --git a/Examples/test-suite/d/director_classes_runme.1.d b/Examples/test-suite/d/director_classes_runme.1.d index 9c34db82a..e753f5f6d 100644 --- a/Examples/test-suite/d/director_classes_runme.1.d +++ b/Examples/test-suite/d/director_classes_runme.1.d @@ -18,6 +18,7 @@ * Base - Val(444.555) * Base - Ref(444.555) * Base - Ptr(444.555) + * Base - ConstPtrRef(444.555) * Base - FullyOverloaded(int 10) * Base - FullyOverloaded(bool 1) * Base - SemiOverloaded(int -678) @@ -28,6 +29,7 @@ * Derived - Val(444.555) * Derived - Ref(444.555) * Derived - Ptr(444.555) + * Derived - ConstPtrRef(444.555) * Derived - FullyOverloaded(int 10) * Derived - FullyOverloaded(bool 1) * Derived - SemiOverloaded(int -678) @@ -38,6 +40,7 @@ * DDerived - Val(444.555) * DDerived - Ref(444.555) * DDerived - Ptr(444.555) + * DDerived - ConstPtrRef(444.555) * DDerived - FullyOverloaded(int 10) * DDerived - FullyOverloaded(bool True) * DDerived - SemiOverloaded(-678) @@ -57,7 +60,7 @@ import director_classes.Derived; import director_classes.DoubleHolder; void main() { - if (PrintDebug) Stdout.formatln("------------ Start ------------ "); + if (PrintDebug) Stdout.formatln("------------ Start ------------"); auto myCaller = new Caller(); @@ -83,7 +86,7 @@ void main() { makeCalls(myCaller, myBase); } - if (PrintDebug) Stdout.formatln("------------ Finish ------------ "); + if (PrintDebug) Stdout.formatln("------------ Finish ------------"); } void makeCalls(Caller myCaller, Base myBase) { @@ -96,6 +99,7 @@ void makeCalls(Caller myCaller, Base myBase) { if (myCaller.ValCall(dh).val != dh.val) throw new Exception("[1] failed"); if (myCaller.RefCall(dh).val != dh.val) throw new Exception("[2] failed"); if (myCaller.PtrCall(dh).val != dh.val) throw new Exception("[3] failed"); + if (myCaller.ConstPtrRefCall(dh).val != dh.val) throw new Exception("[3] failed"); // Fully overloaded method test (all methods in base class are overloaded) if (myCaller.FullyOverloadedCall(10) != myBaseType ~ "::FullyOverloaded(int)") throw new Exception("[4] failed"); @@ -136,6 +140,11 @@ public class DDerived : Base { return x; } + public override DoubleHolder ConstPtrRef(DoubleHolder x) { + if (PrintDebug) Stdout.formatln("DDerived - ConstPtrRef({0:d3})", x.val); + return x; + } + public override char[] FullyOverloaded(int x) { if (PrintDebug) Stdout.formatln("DDerived - FullyOverloaded(int {0})", x); return "DDerived::FullyOverloaded(int)"; diff --git a/Examples/test-suite/d/director_classes_runme.2.d b/Examples/test-suite/d/director_classes_runme.2.d index 98e27b3cd..b16fa5461 100644 --- a/Examples/test-suite/d/director_classes_runme.2.d +++ b/Examples/test-suite/d/director_classes_runme.2.d @@ -18,6 +18,7 @@ * Base - Val(444.555) * Base - Ref(444.555) * Base - Ptr(444.555) + * Base - ConstPtrRef(444.555) * Base - FullyOverloaded(int 10) * Base - FullyOverloaded(bool 1) * Base - SemiOverloaded(int -678) @@ -28,6 +29,7 @@ * Derived - Val(444.555) * Derived - Ref(444.555) * Derived - Ptr(444.555) + * Derived - ConstPtrRef(444.555) * Derived - FullyOverloaded(int 10) * Derived - FullyOverloaded(bool 1) * Derived - SemiOverloaded(int -678) @@ -38,6 +40,7 @@ * DDerived - Val(444.555) * DDerived - Ref(444.555) * DDerived - Ptr(444.555) + * DDerived - ConstPtrRef(444.555) * DDerived - FullyOverloaded(int 10) * DDerived - FullyOverloaded(bool true) * DDerived - SemiOverloaded(-678) @@ -58,7 +61,7 @@ import director_classes.Derived; import director_classes.DoubleHolder; void main() { - if (PrintDebug) writeln("------------ Start ------------ "); + if (PrintDebug) writeln("------------ Start ------------"); auto myCaller = new Caller(); @@ -84,7 +87,7 @@ void main() { makeCalls(myCaller, myBase); } - if (PrintDebug) writeln("------------ Finish ------------ "); + if (PrintDebug) writeln("------------ Finish ------------"); } void makeCalls(Caller myCaller, Base myBase) { @@ -97,6 +100,7 @@ void makeCalls(Caller myCaller, Base myBase) { enforce(myCaller.ValCall(dh).val == dh.val, "[1] failed"); enforce(myCaller.RefCall(dh).val == dh.val, "[2] failed"); enforce(myCaller.PtrCall(dh).val == dh.val, "[3] failed"); + enforce(myCaller.ConstPtrRefCall(dh).val == dh.val, "[3] failed"); // Fully overloaded method test (all methods in base class are overloaded) enforce(myCaller.FullyOverloadedCall(10) == myBaseType ~ "::FullyOverloaded(int)", "[4] failed"); @@ -137,6 +141,11 @@ public class DDerived : Base { return x; } + public override DoubleHolder ConstPtrRef(DoubleHolder x) { + if (PrintDebug) writefln("DDerived - ConstPtrRef(%s)", x.val); + return x; + } + public override string FullyOverloaded(int x) { if (PrintDebug) writefln("DDerived - FullyOverloaded(int %s)", x); return "DDerived::FullyOverloaded(int)"; diff --git a/Examples/test-suite/d/li_boost_shared_ptr_director_runme.2.d b/Examples/test-suite/d/li_boost_shared_ptr_director_runme.2.d new file mode 100644 index 000000000..fbcb03fa6 --- /dev/null +++ b/Examples/test-suite/d/li_boost_shared_ptr_director_runme.2.d @@ -0,0 +1,114 @@ +module li_boost_shared_ptr_director_runme; + +import std.conv; +import std.exception; +import std.stdio; +import std.string; +import li_boost_shared_ptr_director.li_boost_shared_ptr_director; +import li_boost_shared_ptr_director.Base; +import li_boost_shared_ptr_director.C; + +void check(int got, int expected) { + enforce(got == expected, "Failed. got: " ~ to!string(got) ~ " Expected: " ~ to!string(expected)); +} + +void main() { + Derived a = new Derived(false); + Derived b = new Derived(true); + + check(call_ret_c_shared_ptr(a), 1); + check(call_ret_c_shared_ptr(b), -1); + check(call_ret_c_by_value(a), 1); + + check(call_ret_c_shared_ptr(a), 1); + check(call_ret_c_shared_ptr(b), -1); + check(call_ret_c_by_value(a), 1); + + check(call_take_c_by_value(a), 5); + check(call_take_c_by_ref(a), 6); + check(call_take_c_by_pointer(a), 7); + check(call_take_c_by_pointer_ref(a), 8); + check(call_take_c_shared_ptr_by_value(a), 9); + check(call_take_c_shared_ptr_by_ref(a), 10); + check(call_take_c_shared_ptr_by_pointer(a), 11); + check(call_take_c_shared_ptr_by_pointer_ref(a), 12); + + check(call_take_c_by_pointer_with_null(a), -2); + check(call_take_c_by_pointer_ref_with_null(a), -3); + check(call_take_c_shared_ptr_by_value_with_null(a), -4); + check(call_take_c_shared_ptr_by_ref_with_null(a), -5); + check(call_take_c_shared_ptr_by_pointer_with_null(a), -6); + check(call_take_c_shared_ptr_by_pointer_ref_with_null(a), -7); +} + +public class Derived : Base { + + private bool return_none; + + public this(bool flag) { + super(); + this.return_none = flag; + } + + public override C ret_c_shared_ptr() { + if (this.return_none) + return null; + else + return new C(); + } + + public override C ret_c_by_value() { + return new C(); + } + + public override int take_c_by_value(C c) { + return c.get_m(); + } + + public override int take_c_by_ref(C c) { + return c.get_m(); + } + + public override int take_c_by_pointer(C c) { + if (c !is null) + return c.get_m(); + else + return -2; + } + + public override int take_c_by_pointer_ref(C c) { + if (c !is null) + return c.get_m(); + else + return -3; + } + + public override int take_c_shared_ptr_by_value(C c) { + if (c !is null) + return c.get_m(); + else + return -4; + } + + public override int take_c_shared_ptr_by_ref(C c) { + if (c !is null) + return c.get_m(); + else + return -5; + } + + public override int take_c_shared_ptr_by_pointer(C c) { + if (c !is null) + return c.get_m(); + else + return -6; + } + + public override int take_c_shared_ptr_by_pointer_ref(C c) { + if (c !is null) + return c.get_m(); + else + return -7; + } + +} diff --git a/Examples/test-suite/d/preproc_constants_c_runme.1.d b/Examples/test-suite/d/preproc_constants_c_runme.1.d index d846c71ac..a6c2f3d10 100644 --- a/Examples/test-suite/d/preproc_constants_c_runme.1.d +++ b/Examples/test-suite/d/preproc_constants_c_runme.1.d @@ -36,7 +36,7 @@ void main() { static assert(is(char[] == typeof(CONST_STRING2()))); static assert(is(int == typeof(INT_AND_BOOL()))); -// static assert(is(int == typeof(INT_AND_CHAR()))); + static assert(is(int == typeof(INT_AND_CHAR()))); static assert(is(int == typeof(INT_AND_INT()))); static assert(is(uint == typeof(INT_AND_UINT()))); static assert(is(c_long == typeof(INT_AND_LONG()))); @@ -61,4 +61,7 @@ void main() { static assert(is(int == typeof(EXPR_LAND()))); static assert(is(int == typeof(EXPR_LOR()))); static assert(is(double == typeof(EXPR_CONDITIONAL()))); + static assert(is(double == typeof(EXPR_MIXED1()))); + static assert(is(int == typeof(EXPR_WCHAR_MAX()))); + static assert(is(int == typeof(EXPR_WCHAR_MIN()))); } diff --git a/Examples/test-suite/d/preproc_constants_c_runme.2.d b/Examples/test-suite/d/preproc_constants_c_runme.2.d index 9bdbb9372..786cb48cc 100644 --- a/Examples/test-suite/d/preproc_constants_c_runme.2.d +++ b/Examples/test-suite/d/preproc_constants_c_runme.2.d @@ -36,7 +36,7 @@ void main() { static assert(is(string == typeof(CONST_STRING2()))); static assert(is(int == typeof(INT_AND_BOOL()))); -// static assert(is(int == typeof(INT_AND_CHAR()))); + static assert(is(int == typeof(INT_AND_CHAR()))); static assert(is(int == typeof(INT_AND_INT()))); static assert(is(uint == typeof(INT_AND_UINT()))); static assert(is(c_long == typeof(INT_AND_LONG()))); @@ -61,4 +61,7 @@ void main() { static assert(is(int == typeof(EXPR_LAND()))); static assert(is(int == typeof(EXPR_LOR()))); static assert(is(double == typeof(EXPR_CONDITIONAL()))); + static assert(is(double == typeof(EXPR_MIXED1()))); + static assert(is(int == typeof(EXPR_WCHAR_MAX()))); + static assert(is(int == typeof(EXPR_WCHAR_MIN()))); } diff --git a/Examples/test-suite/d/preproc_constants_runme.1.d b/Examples/test-suite/d/preproc_constants_runme.1.d index 009405fc7..85fa918e4 100644 --- a/Examples/test-suite/d/preproc_constants_runme.1.d +++ b/Examples/test-suite/d/preproc_constants_runme.1.d @@ -35,7 +35,7 @@ void main() { static assert(is(char[] == typeof(CONST_STRING2()))); static assert(is(int == typeof(INT_AND_BOOL()))); -// static assert(is(int == typeof(INT_AND_CHAR()))); + static assert(is(int == typeof(INT_AND_CHAR()))); static assert(is(int == typeof(INT_AND_INT()))); static assert(is(uint == typeof(INT_AND_UINT()))); static assert(is(c_long == typeof(INT_AND_LONG()))); @@ -60,4 +60,7 @@ void main() { static assert(is(bool == typeof(EXPR_LAND()))); static assert(is(bool == typeof(EXPR_LOR()))); static assert(is(double == typeof(EXPR_CONDITIONAL()))); + static assert(is(double == typeof(EXPR_MIXED1()))); + static assert(is(int == typeof(EXPR_WCHAR_MAX()))); + static assert(is(int == typeof(EXPR_WCHAR_MIN()))); } diff --git a/Examples/test-suite/d/preproc_constants_runme.2.d b/Examples/test-suite/d/preproc_constants_runme.2.d index 2d92ef052..c81e53160 100644 --- a/Examples/test-suite/d/preproc_constants_runme.2.d +++ b/Examples/test-suite/d/preproc_constants_runme.2.d @@ -35,7 +35,7 @@ void main() { static assert(is(string == typeof(CONST_STRING2()))); static assert(is(int == typeof(INT_AND_BOOL()))); -// static assert(is(int == typeof(INT_AND_CHAR()))); + static assert(is(int == typeof(INT_AND_CHAR()))); static assert(is(int == typeof(INT_AND_INT()))); static assert(is(uint == typeof(INT_AND_UINT()))); static assert(is(c_long == typeof(INT_AND_LONG()))); @@ -60,4 +60,7 @@ void main() { static assert(is(bool == typeof(EXPR_LAND()))); static assert(is(bool == typeof(EXPR_LOR()))); static assert(is(double == typeof(EXPR_CONDITIONAL()))); + static assert(is(double == typeof(EXPR_MIXED1()))); + static assert(is(int == typeof(EXPR_WCHAR_MAX()))); + static assert(is(int == typeof(EXPR_WCHAR_MIN()))); } diff --git a/Examples/test-suite/d/proxycode_runme.2.d b/Examples/test-suite/d/proxycode_runme.2.d new file mode 100644 index 000000000..133217f2e --- /dev/null +++ b/Examples/test-suite/d/proxycode_runme.2.d @@ -0,0 +1,41 @@ +module proxycode_runme; + +import std.exception; +import proxycode.Proxy1; +import proxycode.Proxy2; +import proxycode.Proxy3; +import proxycode.Proxy4; +import proxycode.Proxy5a; +import proxycode.Proxy5b; +import proxycode.Proxy6; + +void main() { + if (new Proxy1().proxycode1(100) != 101) + throw new Exception("Fail"); + + if (new Proxy1().proxycode1(100) != 101) + throw new Exception("Fail"); + if (new Proxy2().proxycode2a(100) != 102) + throw new Exception("Fail"); + if (new Proxy2().proxycode2b(100) != 102) + throw new Exception("Fail"); + if (new Proxy3().proxycode3(100) != 103) + throw new Exception("Fail"); + + if (new Proxy4().proxycode4(100) != 104) + throw new Exception("Fail"); +// if (new Proxy4.Proxy4Nested().proxycode4nested(100) != 144) +// throw new Exception("Fail"); + + if (new Proxy5a().proxycode5(100) != 100) + throw new Exception("Fail"); + if (new Proxy5b().proxycode5(100) != 100) + throw new Exception("Fail"); + if (new Proxy5b().proxycode5(100, 100) != 255) + throw new Exception("Fail"); + + uint t1 = 10; + uint t2 = 100; + Proxy6 p = new Proxy6().proxyUseT(t1, t2); + p.useT(t1, t2); +} diff --git a/Examples/test-suite/default_arg_expressions.i b/Examples/test-suite/default_arg_expressions.i new file mode 100644 index 000000000..d83dc05bc --- /dev/null +++ b/Examples/test-suite/default_arg_expressions.i @@ -0,0 +1,34 @@ +%module default_arg_expressions + +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ptr; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) UsdGeomTokensPtr; +%immutable UsdGeomTokens; + +%inline %{ +struct Numbers { + int val; + int *ptr; + Numbers() : val(), ptr(&val) {} +}; +struct TfToken { + Numbers val; + Numbers *ptr; + TfToken() : val(), ptr(&val) {} +}; +struct Tokens { + const TfToken face; + const TfToken *pface; + Tokens() : face(), pface(&face) {} +}; +static Tokens UsdGeomTokens; +static Tokens *UsdGeomTokensPtr = &UsdGeomTokens; +void CreateMaterialBindSubset1(const Tokens &elementType = UsdGeomTokens) {} +void CreateMaterialBindSubset2(int num = UsdGeomTokensPtr->pface->val.val) {} +void CreateMaterialBindSubset3(int num = UsdGeomTokensPtr->pface->ptr->val) {} +void CreateMaterialBindSubset4(int num = UsdGeomTokensPtr->face.val.val) {} +//void CreateMaterialBindSubset5(int num = UsdGeomTokens.face.val.val) {} +%} diff --git a/Examples/test-suite/default_args.i b/Examples/test-suite/default_args.i index 02d860765..6b680f561 100644 --- a/Examples/test-suite/default_args.i +++ b/Examples/test-suite/default_args.i @@ -2,26 +2,51 @@ %module default_args +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %{ #if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) + #pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned #endif %} +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) +#define TESTCASE_THROW2(T1, T2) throw(T1, T2) +%{ +#define TESTCASE_THROW1(T1) +#define TESTCASE_THROW2(T1, T2) +%} + %include %inline %{ #include // All kinds of numbers: hex, octal (which pose special problems to Python), negative... - void trickyvalue1(int first, int pos = -1) {} - void trickyvalue2(int first, unsigned rgb = 0xabcdef) {} - void trickyvalue3(int first, int mode = 0644) {} + + class TrickyInPython { + public: + int value_m1(int first, int pos = -1) { return pos; } + unsigned value_0xabcdef(int first, unsigned rgb = 0xabcdef) { return rgb; } + int value_0644(int first, int mode = 0644) { return mode; } + int value_perm(int first, int mode = 0640 | 0004) { return mode; } + int value_m01(int first, int val = -01) { return val; } + bool booltest2(bool x = 0 | 1) { return x; } + int max_32bit_int1(int a = 0x7FFFFFFF) { return a; } + int max_32bit_int2(int a = 2147483647) { return a; } + int min_32bit_int1(int a = -0x80000000) { return a; } + long long too_big_32bit_int1(long long a = 0x80000000) { return a; } + long long too_big_32bit_int2(long long a = 2147483648LL) { return a; } + long long too_small_32bit_int1(long long a = -0x80000001) { return a; } + long long too_small_32bit_int2(long long a = -2147483649LL) { return a; } + }; void doublevalue1(int first, double num = 0.0e-1) {} void doublevalue2(int first, double num = -0.0E2) {} - // Long long arguments are not handled at Python level currently but still work. void seek(long long offset = 0LL) {} void seek2(unsigned long long offset = 0ULL) {} void seek3(long offset = 0L) {} @@ -152,6 +177,9 @@ int double_if_handle_is_null(int n, MyHandle h = 0) { return h ? n : 2*n; } int double_if_dbl_ptr_is_null(int n, double* null_by_default) { return null_by_default ? n : 2*n; } + + void defaulted1(unsigned offset = -1U) {} // minus unsigned! + void defaulted2(int offset = -1U) {} // minus unsigned! }; int Foo::bar = 1; int Foo::spam = 2; @@ -182,18 +210,18 @@ // Default parameters with exception specifications %inline %{ -void exceptionspec(int a = -1) throw (int, const char*) { +void exceptionspec(int a = -1) TESTCASE_THROW2(int, const char*) { if (a == -1) throw "ciao"; else throw a; } struct Except { - Except(bool throwException, int a = -1) throw (int) { + Except(bool throwException, int a = -1) TESTCASE_THROW1(int) { if (throwException) throw a; } - void exspec(int a = 0) throw (int, const char*) { + void exspec(int a = 0) TESTCASE_THROW2(int, const char*) { ::exceptionspec(a); } }; diff --git a/Examples/test-suite/default_args_c.i b/Examples/test-suite/default_args_c.i index e0c0af056..f507aa797 100644 --- a/Examples/test-suite/default_args_c.i +++ b/Examples/test-suite/default_args_c.i @@ -1,5 +1,13 @@ %module default_args_c +%{ +#if defined(__clang__) +#pragma clang diagnostic push +// Suppress: use of logical '||' with constant operand +#pragma clang diagnostic ignored "-Wconstant-logical-operand" +#endif +%} + /* Default arguments for C code */ int foo1(int x = 42 || 3); int foo43(int x = 42 | 3); @@ -12,3 +20,34 @@ int foo43(int x) { return x; } %} + +%inline %{ +struct FooStruct { + int num; +}; +%} +%extend FooStruct { + void no_arg() {} + void one_req(int *required) {} + void one_opt(int *optional = NULL) {} + void two_arg(int *required, int *optional = NULL) {} +} + +%inline %{ +struct StaticStruct { + int snum; +}; +%} +%extend StaticStruct { + static void no_arg() {} + static void one_req(int *required) {} + static void one_opt(int *optional = NULL) {} + static void two_arg(int *required, int *optional = NULL) {} +} + +%{ +void global_opts1(int *optional) {} +void global_opts2(int *required, int *optional) {} +%} +void global_opts1(int *optional = NULL) {} +void global_opts2(int *required, int *optional = NULL) {} diff --git a/Examples/test-suite/derived_byvalue.i b/Examples/test-suite/derived_byvalue.i index a251a8fc6..21de809a5 100644 --- a/Examples/test-suite/derived_byvalue.i +++ b/Examples/test-suite/derived_byvalue.i @@ -1,5 +1,9 @@ %module derived_byvalue +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %inline %{ struct Foo { diff --git a/Examples/test-suite/destructor_methodmodifiers.i b/Examples/test-suite/destructor_methodmodifiers.i new file mode 100644 index 000000000..93db7f2cc --- /dev/null +++ b/Examples/test-suite/destructor_methodmodifiers.i @@ -0,0 +1,61 @@ +%module destructor_methodmodifiers + +// This test changes the proxy classes so that they cannot be inherited from in the target language +// Previously the %csmethodmodifiers, %dmethodmodifiers, %javamethodmodifiers on destructors were ignored +// Now they can control the dispose/Dispose/delete method modifiers + +#if defined(SWIGCSHARP) + +// remove all use of protected and virtual keywords +%typemap(csclassmodifiers) NotForDeriving1, NotForDeriving2 "public sealed class" +%csmethodmodifiers NotForDeriving1::~NotForDeriving1 "public /*not virtual nor override*/"; +%csmethodmodifiers NotForDeriving2::~NotForDeriving2 "public /*not virtual nor override*/"; + +// remove protected keyword to remove compiler warning +%typemap(csbody) NotForDeriving1, NotForDeriving2 %{ + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private /*protected*/ bool swigCMemOwn; + + internal $csclassname(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } +%} + +#elif defined(SWIGD) + +%typemap(dclassmodifiers) NotForDeriving1, NotForDeriving2 "final class" +%dmethodmodifiers NotForDeriving1::~NotForDeriving1 "public final"; +%dmethodmodifiers NotForDeriving2::~NotForDeriving2 "public final"; + +#elif defined(SWIGJAVA) + +%typemap(javaclassmodifiers) NotForDeriving1, NotForDeriving2 "public final class" +%javamethodmodifiers NotForDeriving1::~NotForDeriving1 "public synchronized final"; +%javamethodmodifiers NotForDeriving2::~NotForDeriving2 "public synchronized final"; + +#endif + +%inline %{ +//#include +struct NotForDeriving1 { + void notvirtual() {} + ~NotForDeriving1() { +// std::cout << "~NotForDeriving1 called" << std::endl; + } +}; +struct NotForDeriving2 { + void notvirtual() {} +#if defined(SWIG) +%extend { + ~NotForDeriving2() { +// std::cout << "~NotForDeriving2 called" << std::endl; + } +} +#endif +}; +%} diff --git a/Examples/test-suite/director_basic.i b/Examples/test-suite/director_basic.i index 4c258b097..07d627589 100644 --- a/Examples/test-suite/director_basic.i +++ b/Examples/test-suite/director_basic.i @@ -1,5 +1,9 @@ %module(directors="1") director_basic +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %warnfilter(SWIGWARN_TYPEMAP_THREAD_UNSAFE,SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) MyClass::pmethod; %{ @@ -65,6 +69,14 @@ %} + %typemap(cscode) MyClass %{ + public void testSwigDerivedClassHasMethod() { + if (SwigDerivedClassHasMethod("nonVirtual", swigMethodTypes3)) + throw new global::System.Exception("non-overriding non-virtual method would be when connecting director"); + if (SwigDerivedClassHasMethod("nonOverride", swigMethodTypes4)) + throw new global::System.Exception("non-overriding virtual method would be when connecting director"); + } + %} %feature("director") MyClass; @@ -121,6 +133,29 @@ public: static Bar * call_pmethod(MyClass *myclass, Bar *b) { return myclass->pmethod(b); } + + virtual int nonVirtual() + { + return 100; + } + + virtual int nonOverride() + { + return 101; + } + + static int call_nonVirtual(MyClass *myclass) + { + return myclass->nonVirtual(); + } + + static int call_nonOverride(MyClass *myclass) + { + return myclass->nonOverride(); + } + + // Collisions with generated method names + virtual void Connect() { } }; template diff --git a/Examples/test-suite/director_classes.i b/Examples/test-suite/director_classes.i index 98c29e88c..52342bfc8 100644 --- a/Examples/test-suite/director_classes.i +++ b/Examples/test-suite/director_classes.i @@ -3,6 +3,11 @@ %warnfilter(SWIGWARN_TYPEMAP_THREAD_UNSAFE,SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) Base::Ref; %warnfilter(SWIGWARN_TYPEMAP_THREAD_UNSAFE,SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) Base::Ptr; +%warnfilter(SWIGWARN_TYPEMAP_THREAD_UNSAFE,SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) Base::ConstPtrRef; + +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif %module(directors="1") director_classes @@ -43,6 +48,7 @@ public: virtual DoubleHolder Val(DoubleHolder x) { if (PrintDebug) std::cout << "Base - Val(" << x.val << ")" << std::endl; return x; } virtual DoubleHolder& Ref(DoubleHolder& x) { if (PrintDebug) std::cout << "Base - Ref(" << x.val << ")" << std::endl; return x; } virtual DoubleHolder* Ptr(DoubleHolder* x) { if (PrintDebug) std::cout << "Base - Ptr(" << x->val << ")" << std::endl; return x; } + virtual DoubleHolder *const& ConstPtrRef(DoubleHolder *const& cprx) { if (PrintDebug) std::cout << "Base - ConstPtrRef(" << cprx->val << ")" << std::endl; return cprx; } virtual std::string FullyOverloaded(int x) { if (PrintDebug) std::cout << "Base - FullyOverloaded(int " << x << ")" << std::endl; return "Base::FullyOverloaded(int)"; } virtual std::string FullyOverloaded(bool x) { if (PrintDebug) std::cout << "Base - FullyOverloaded(bool " << x << ")" << std::endl; return "Base::FullyOverloaded(bool)"; } @@ -68,6 +74,7 @@ public: virtual DoubleHolder Val(DoubleHolder x) { if (PrintDebug) std::cout << "Derived - Val(" << x.val << ")" << std::endl; return x; } virtual DoubleHolder& Ref(DoubleHolder& x) { if (PrintDebug) std::cout << "Derived - Ref(" << x.val << ")" << std::endl; return x; } virtual DoubleHolder* Ptr(DoubleHolder* x) { if (PrintDebug) std::cout << "Derived - Ptr(" << x->val << ")" << std::endl; return x; } + virtual DoubleHolder *const& ConstPtrRef(DoubleHolder *const& cprx) { if (PrintDebug) std::cout << "Derived - ConstPtrRef(" << cprx->val << ")" << std::endl; return cprx; } virtual std::string FullyOverloaded(int x) { if (PrintDebug) std::cout << "Derived - FullyOverloaded(int " << x << ")" << std::endl; return "Derived::FullyOverloaded(int)"; } virtual std::string FullyOverloaded(bool x) { if (PrintDebug) std::cout << "Derived - FullyOverloaded(bool " << x << ")" << std::endl; return "Derived::FullyOverloaded(bool)"; } @@ -99,6 +106,7 @@ public: DoubleHolder ValCall(DoubleHolder x) { return m_base->Val(x); } DoubleHolder& RefCall(DoubleHolder& x) { return m_base->Ref(x); } DoubleHolder* PtrCall(DoubleHolder* x) { return m_base->Ptr(x); } + DoubleHolder *const& ConstPtrRefCall(DoubleHolder *const& cprx) { return m_base->ConstPtrRef(cprx); } std::string FullyOverloadedCall(int x) { return m_base->FullyOverloaded(x); } std::string FullyOverloadedCall(bool x) { return m_base->FullyOverloaded(x); } std::string SemiOverloadedCall(int x) { return m_base->SemiOverloaded(x); } diff --git a/Examples/test-suite/director_exception.i b/Examples/test-suite/director_exception.i index 2559ae566..71366bef0 100644 --- a/Examples/test-suite/director_exception.i +++ b/Examples/test-suite/director_exception.i @@ -3,42 +3,47 @@ %warnfilter(SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) return_const_char_star; %{ - -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - #include - // define dummy director exception classes to prevent spurious errors // in target languages that do not support directors. #ifndef SWIG_DIRECTORS namespace Swig { -class DirectorException {}; -class DirectorMethodException: public Swig::DirectorException {}; + class DirectorException {}; + class DirectorMethodException: public Swig::DirectorException {}; } - #ifndef SWIG_fail - #define SWIG_fail - #endif #endif /* !SWIG_DIRECTORS */ - %} %include "std_string.i" -#ifdef SWIGPYTHON +#ifdef SWIGPHP %feature("director:except") { - if ($error != NULL) { - throw Swig::DirectorMethodException(); - } + if ($error == FAILURE) { + Swig::DirectorMethodException::raise("$symname"); + } } %exception { - try { $action } - catch (Swig::DirectorException &) { SWIG_fail; } + try { $action } + catch (Swig::DirectorException &) { SWIG_fail; } +} + +#endif + +#ifdef SWIGPYTHON + +%feature("director:except") { + if ($error != NULL) { + Swig::DirectorMethodException::raise("$symname"); + } +} + +%exception { + try { $action } + catch (Swig::DirectorException &) { SWIG_fail; } } #endif @@ -56,12 +61,12 @@ class DirectorMethodException: public Swig::DirectorException {}; // Change back to old 2.0 default behavior %feature("director:except") { - jthrowable $error = jenv->ExceptionOccurred(); - if ($error) { - // Dont clear exception, still be active when return to java execution - // Essentially ignore exception occurred -- old behavior. - return $null; - } + jthrowable $error = jenv->ExceptionOccurred(); + if ($error) { + // Dont clear exception, still be active when return to java execution + // Essentially ignore exception occurred -- old behavior. + return $null; + } } #endif @@ -69,7 +74,7 @@ class DirectorMethodException: public Swig::DirectorException {}; #ifdef SWIGRUBY %feature("director:except") { - throw Swig::DirectorMethodException($error); + Swig::DirectorMethodException::raise($error); } %exception { @@ -110,6 +115,18 @@ Foo *launder(Foo *f) { %feature("director") Bar; %feature("director") ReturnAllTypes; +%{ +// throw is deprecated in C++11 and invalid in C++17 and later +#if defined(__cplusplus) && __cplusplus >= 201103L +#define throw(TYPE1, TYPE2, TYPE3) +#else +#define throw(TYPE1, TYPE2, TYPE3) throw(TYPE1, TYPE2, TYPE3) +#if defined(_MSC_VER) + #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif +#endif +%} + %inline %{ struct Exception1 { @@ -122,16 +139,15 @@ Foo *launder(Foo *f) { class Base { public: - virtual ~Base() throw () {} + virtual ~Base() {} }; class Bar : public Base { public: - virtual std::string ping() throw (Exception1, Exception2&) { return "Bar::ping()"; } - virtual std::string pong() throw (Unknown1, int, Unknown2&) { return "Bar::pong();" + ping(); } - virtual std::string pang() throw () { return "Bar::pang()"; } + virtual std::string ping() throw(Exception1, Exception2&, double) { return "Bar::ping()"; } + virtual std::string pong() throw(Unknown1, int, Unknown2&) { return "Bar::pong();" + ping(); } }; // Class to allow regression testing SWIG/PHP not checking if an exception diff --git a/Examples/test-suite/director_exception_catches.i b/Examples/test-suite/director_exception_catches.i new file mode 100644 index 000000000..ad183665f --- /dev/null +++ b/Examples/test-suite/director_exception_catches.i @@ -0,0 +1,25 @@ +%module(directors="1") director_exception_catches + +%include +%feature("director") BaseClass; + +%{ +// define dummy director exception classes to prevent spurious errors +// in target languages that do not support directors. + +#ifndef SWIG_DIRECTORS +namespace Swig { + class DirectorException {}; +} +#endif /* !SWIG_DIRECTORS */ +%} + +%catches(Swig::DirectorException) BaseClass::call_description; + +%inline %{ +struct BaseClass { + virtual std::string description() const = 0; + static std::string call_description(BaseClass& bc) { return bc.description(); } + virtual ~BaseClass() {} +}; +%} diff --git a/Examples/test-suite/director_exception_nothrow.i b/Examples/test-suite/director_exception_nothrow.i new file mode 100644 index 000000000..8a072617f --- /dev/null +++ b/Examples/test-suite/director_exception_nothrow.i @@ -0,0 +1,28 @@ +%module(directors="1") director_exception_nothrow + +%include "std_string.i" + +%feature("director") Bar; + +%{ +#if defined(_MSC_VER) + #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif +%} + +%inline %{ +#include + +class Base +{ +public: + virtual ~Base() throw() {} +}; + + +class Bar : public Base +{ +public: + virtual std::string pang() throw() { return "Bar::pang()"; } +}; +%} diff --git a/Examples/test-suite/director_extend.i b/Examples/test-suite/director_extend.i index cec930a42..60a9d4cf0 100644 --- a/Examples/test-suite/director_extend.i +++ b/Examples/test-suite/director_extend.i @@ -25,7 +25,7 @@ namespace Swig { size_t ExceptionMethod() { // Check positioning of director code in wrapper file -// Below is what we really want to test, but director exceptions vary too much across across all languages +// Below is what we really want to test, but director exceptions vary too much across all languages // throw Swig::DirectorException("DirectorException was not in scope!!"); // Instead check definition of Director class as that is defined in the same place as DirectorException (director.swg) size_t size = sizeof(Swig::Director); diff --git a/Examples/test-suite/director_overload.i b/Examples/test-suite/director_overload.i index 55bdf2caa..604ffe5ca 100644 --- a/Examples/test-suite/director_overload.i +++ b/Examples/test-suite/director_overload.i @@ -1,5 +1,9 @@ %module(directors="1") director_overload +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %feature("director"); #ifdef SWIGPYTHON diff --git a/Examples/test-suite/director_ownership.i b/Examples/test-suite/director_ownership.i new file mode 100644 index 000000000..48e909758 --- /dev/null +++ b/Examples/test-suite/director_ownership.i @@ -0,0 +1,72 @@ +%module(directors="1") director_ownership + +// Github issue #1184 + +%include "std_string.i" + +%feature("director") example::ContentBase; +%feature("director") example::ContentDerived; + +%newobject example::make_content; + +%inline %{ +#include + +namespace example +{ + +class ContentBase +{ +public: + ContentBase() {} + virtual ~ContentBase() {} + virtual std::string get_name() const = 0; +}; + + +class ContentDerived: public ContentBase +{ +public: + ContentDerived():ContentBase() { m_name = "ContentDerived"; } + virtual ~ContentDerived() {} + virtual std::string get_name() const { return m_name; } + +private: + std::string m_name; +}; + + +class Container +{ +public: + Container() { m_content = 0; } + ~Container() + { + clear_content(); + } + // the container takes the ownership of the content + void set_content(ContentBase* content) + { + clear_content(); + m_content = content; + } + ContentBase* get_content() { return m_content; } + +private: + void clear_content() + { + if(m_content) + { + delete m_content; + m_content = 0; + } + } + +private: + ContentBase* m_content; +}; + +static ContentBase* make_content() { return new ContentDerived(); } + +} // namespace example +%} diff --git a/Examples/test-suite/director_property.i b/Examples/test-suite/director_property.i index da37ca4ae..d64e0c439 100644 --- a/Examples/test-suite/director_property.i +++ b/Examples/test-suite/director_property.i @@ -2,6 +2,10 @@ %warnfilter(SWIGWARN_TYPEMAP_THREAD_UNSAFE,SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) MyClass::pmethod; +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %{ #include diff --git a/Examples/test-suite/director_smartptr.i b/Examples/test-suite/director_smartptr.i index 9d0be80f0..d016af17e 100644 --- a/Examples/test-suite/director_smartptr.i +++ b/Examples/test-suite/director_smartptr.i @@ -44,7 +44,6 @@ public: %include %shared_ptr(Foo) - %feature("director") Foo; class FooBar { @@ -72,5 +71,12 @@ public: static Foo* get_self(Foo *self_); }; +%shared_ptr(FooDerived) +%feature("director") FooDerived; + +%inline %{ +struct FooDerived : Foo { +}; +%} #endif diff --git a/Examples/test-suite/director_thread.i b/Examples/test-suite/director_thread.i index 2732eb907..c4564737f 100644 --- a/Examples/test-suite/director_thread.i +++ b/Examples/test-suite/director_thread.i @@ -7,29 +7,51 @@ %module(directors="1") director_thread #endif +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + +%begin %{ +#define SWIG_JAVA_USE_THREAD_NAME +//#define DEBUG_DIRECTOR_THREAD_NAME +%} + %{ #ifdef _WIN32 #include #include +#include #else #include +#include +#include #include #include #endif -#include +#include +#include "swig_examples_lock.h" class Foo; extern "C" { #ifdef _WIN32 - unsigned int __stdcall working(void* t); - unsigned int thread_id(0); + static unsigned int __stdcall working(void* t); + static HANDLE thread_handle = 0; #else void* working(void* t); - pthread_t thread; + static pthread_t thread; #endif + static int thread_terminate = 0; - + static SwigExamples::CriticalSection critical_section; + int get_thread_terminate() { + SwigExamples::Lock lock(critical_section); + return thread_terminate; + } + void set_thread_terminate(int value) { + SwigExamples::Lock lock(critical_section); + thread_terminate = value; + } } %} @@ -55,9 +77,10 @@ extern "C" { } void stop() { - thread_terminate = 1; + set_thread_terminate(1); %#ifdef _WIN32 - /*TODO(bhy) what to do for win32? */ + WaitForSingleObject(thread_handle, INFINITE); + CloseHandle(thread_handle); %#else pthread_join(thread, NULL); %#endif @@ -65,13 +88,49 @@ extern "C" { void run() { %#ifdef _WIN32 - _beginthreadex(NULL,0,working,this,0,&thread_id); + unsigned int thread_id = 0; + thread_handle = (HANDLE)_beginthreadex(NULL,0,working,this,0,&thread_id); + if (thread_handle == 0) { + fprintf(stderr, "_beginthreadex failed in run()\n"); + assert(0); + } %#else - pthread_create(&thread,NULL,working,this); + int create = pthread_create(&thread,NULL,working,this); + if (create != 0) { + errno = create; + perror("pthread_create in run()"); + assert(0); + } %#endif MilliSecondSleep(500); } - + + void setThreadName() { +%#ifdef _WIN32 +%#else + +%#ifdef __APPLE__ + int setname = pthread_setname_np("MyThreadName"); +%#else + int setname = pthread_setname_np(pthread_self(), "MyThreadName"); +%#endif + + if (setname != 0) { + errno = setname; + perror("calling pthread_setname_np in setThreadName()"); + assert(0); + } +%#endif + } + + static bool namedThread() { +%#ifdef _WIN32 + return false; +%#else + return true; +%#endif + } + virtual void do_foo() { val += 1; } @@ -87,15 +146,11 @@ extern "C" { #endif { Foo* f = static_cast(t); - while ( ! thread_terminate ) { + f->setThreadName(); + while (!get_thread_terminate()) { MilliSecondSleep(50); f->do_foo(); } -#ifdef _WIN32 - /* TODO(bhy) what's the corresponding of pthread_exit in win32? */ -#else - pthread_exit(0); -#endif return 0; } } diff --git a/Examples/test-suite/director_void.i b/Examples/test-suite/director_void.i new file mode 100644 index 000000000..40f53b6e2 --- /dev/null +++ b/Examples/test-suite/director_void.i @@ -0,0 +1,47 @@ +%module(directors="1") director_void + +%warnfilter(SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) voidPtrOut; + +%feature("director") DirectorVoidPointer; + +#if defined(SWIGCSHARP) +%apply void *VOID_INT_PTR { void * } +#endif + +%inline %{ +class DirectorVoidPointer { + int *ptr; +public: + DirectorVoidPointer(int val) : ptr(new int(val)) {} + virtual ~DirectorVoidPointer() { delete ptr; } + + virtual void * voidPtrOut() { return ptr; } + virtual int voidPtrIn(void *p) { + return nonVirtualVoidPtrIn(p); + } + + void setNewValue(int val) { + delete ptr; + ptr = new int(val); + } + void *nonVirtualVoidPtrOut() { return ptr; } + int nonVirtualVoidPtrIn(void *p) { + int val = *(int *)p; + setNewValue(val + 100); + return *ptr; + } +}; + +struct Caller { + int callVirtualIn(DirectorVoidPointer *d, int num) { + return d->voidPtrIn(&num); + } + int callVirtualOut(DirectorVoidPointer *d) { + return *(int *)d->voidPtrOut(); + } + static int VoidToInt(void *p) { + return *(int *)p; + } +}; +%} + diff --git a/Examples/test-suite/doxygen_alias.i b/Examples/test-suite/doxygen_alias.i new file mode 100644 index 000000000..79cb7964b --- /dev/null +++ b/Examples/test-suite/doxygen_alias.i @@ -0,0 +1,22 @@ +%module doxygen_alias + +#ifdef SWIGJAVA +%feature("doxygen:alias:nullptr") "null" +#elif defined(SWIGPYTHON) +%feature("doxygen:alias:nullptr") "None" +#else +%feature("doxygen:alias:nullptr") "NULL" +#endif + +%inline %{ + +class Something {}; + +/** + A function returning something. + + @returns A new object which may be @nullptr. + */ +Something* make_something() { return 0; } + +%} diff --git a/Examples/test-suite/doxygen_basic_notranslate.i b/Examples/test-suite/doxygen_basic_notranslate.i new file mode 100644 index 000000000..e62be5437 --- /dev/null +++ b/Examples/test-suite/doxygen_basic_notranslate.i @@ -0,0 +1,110 @@ +%module doxygen_basic_notranslate + +%include "doxygen_basic_translate.h" +%feature("doxygen:notranslate") function; +%feature("doxygen:notranslate") function1; +%feature("doxygen:notranslate") function2; +%feature("doxygen:notranslate") function3; +%feature("doxygen:notranslate") function4; +%feature("doxygen:notranslate") function5; +%feature("doxygen:notranslate") function6; +%feature("doxygen:notranslate") function7; + +%inline %{ + +/** + * \brief + * Brief description. + * + * The comment text + * \author Some author + * \return Some number + * \sa function2 + */ +int function() +{ + return 0; +} + +/** Single line comment */ +void function1() +{ +} + +/** + * A test of a very very very very very very very very very very very very very very very very + * very very very very very long comment string. + */ +void function2() +{ +} + +/** + * A test for overloaded functions + * This is function \b one + */ +void function3(int a) +{ +} + +/** + * A test for overloaded functions + * This is function \b two + */ +void function3(int a, int b) +{ +} + +/** + * A test of some mixed tag usage + * \if CONDITION + * This \a code fragment shows us something \. + * \par Minuses: + * \arg it's senseless + * \arg it's stupid + * \arg it's null + * + * \warning This may not work as expected + * + * \code + * int main() { while(true); } + * \endcode + * \endif + */ +void function4() +{ +} + + +void function5(int a) +{ +} +/**< This is a post comment. */ + +/** + * Test for default args + * @param a Some parameter, default is 42 + */ +void function6(int a=42) +{ +} + +class Shape +{ +public: + typedef Shape* superType; +}; + +/** + * Test for a parameter with difficult type + * (mostly for python) + * @param a Very strange param + */ +void function7(Shape::superType *a[10]) +{ +} + +/** + * Comment at the end of file should be ignored. + */ +%} diff --git a/Examples/test-suite/doxygen_basic_translate.h b/Examples/test-suite/doxygen_basic_translate.h new file mode 100644 index 000000000..7b2b3f58a --- /dev/null +++ b/Examples/test-suite/doxygen_basic_translate.h @@ -0,0 +1,5 @@ + +/** + * This file contains only doxygen comment without a declaration - + * it should be ignored by SWIG and must not trigger syntax error. + */ diff --git a/Examples/test-suite/doxygen_basic_translate.i b/Examples/test-suite/doxygen_basic_translate.i new file mode 100644 index 000000000..da4d80909 --- /dev/null +++ b/Examples/test-suite/doxygen_basic_translate.i @@ -0,0 +1,113 @@ +%module doxygen_basic_translate + +%include "doxygen_basic_translate.h" + +%inline %{ + +/** + * \brief + * Brief description. + * + * The comment text. + * + * \author Some author + * + * \return Some number + * + * \sa function2 + */ +int function() +{ + return 0; +} + +/** + * A test of a very very very very very very very very very very very very very very very very + * very very very very very long comment string. + */ +void function2() +{ +} + +/** + * A test for overloaded functions + * This is function \b one + */ +void function3(int a) +{ +} + +/** + * A test for overloaded functions + * This is function \b two + */ +void function3(int a, int b) +{ +} + +/** + * A test of some mixed tag usage + * \if CONDITION + * This \a code fragment shows us something \. + * \par Minuses: + * \arg it's senseless + * \arg it's stupid + * \arg it's null + * + * \warning This may not work as expected + * \code + * int main() { while(true); } + * + * // Test blank line in code block + * \endcode + * \endif + */ +void function4() +{ +} + + +void function5(int a) +{ +} +/**< This is a post comment. */ + +/** + * Test for default args + * @param a Some parameter, default is 42 + */ +void function6(int a=42) +{ +} + +class Shape +{ +public: + typedef Shape* superType; +}; + +/** + * Test for a parameter with difficult type + * (mostly for python) + * @param a Very strange param + */ +void function7(Shape::superType *a[10]) +{ +} + +/** + Multiple parameters test. + + @param y Vertical coordinate. + @param x Horizontal coordinate. + @return Arc tangent of @c y/x. + */ +double Atan2(double y, double x) +{ + return 0; +} + +/** + * Comment at the end of file should be ignored. + */ +%} diff --git a/Examples/test-suite/doxygen_basic_translate_style2.i b/Examples/test-suite/doxygen_basic_translate_style2.i new file mode 100644 index 000000000..32e3cfcbe --- /dev/null +++ b/Examples/test-suite/doxygen_basic_translate_style2.i @@ -0,0 +1,107 @@ +%module doxygen_basic_translate_style2 + +%include "doxygen_basic_translate.h" + +// This test demonstrates a doxygen comment style that starts on the +// first line and so uses extra spacing in subsequent lines. + +%inline %{ + +/** \brief + * Brief description. + * + * The comment text. + * + * \author Some author + * + * \return Some number + * + * \sa function2 + */ +int function() +{ + return 0; +} + +/** A test of a very very very very very very very very very very very very very very very very + * very very very very very long comment string. + */ +void function2() +{ +} + +/** A test for overloaded functions + * This is function \b one + */ +void function3(int a) +{ +} + +/** A test for overloaded functions + * This is function \b two + */ +void function3(int a, int b) +{ +} + +/** A test of some mixed tag usage + * \if CONDITION + * This \a code fragment shows us something \. + * \par Minuses: + * \arg it's senseless + * \arg it's stupid + * \arg it's null + * + * \warning This may not work as expected + * \code + * int main() { while(true); } + * + * // Test blank line in code block + * \endcode + * \endif + */ +void function4() +{ +} + + +void function5(int a) +{ +} +/**< This is a post comment. */ + +/** Test for default args + * @param a Some parameter, default is 42 + */ +void function6(int a=42) +{ +} + +class Shape +{ +public: + typedef Shape* superType; +}; + +/** Test for a parameter with difficult type + * (mostly for python) + * @param a Very strange param + */ +void function7(Shape::superType *a[10]) +{ +} + +/** Multiple parameters test. + * + * @param y Vertical coordinate. + * @param x Horizontal coordinate. + * @return Arc tangent of @c y/x. + */ +double Atan2(double y, double x) +{ + return 0; +} + +/** Comment at the end of file should be ignored. + */ +%} diff --git a/Examples/test-suite/doxygen_ignore.i b/Examples/test-suite/doxygen_ignore.i new file mode 100644 index 000000000..8e5449f43 --- /dev/null +++ b/Examples/test-suite/doxygen_ignore.i @@ -0,0 +1,41 @@ +%module doxygen_ignore + +%feature("doxygen:ignore:transferfull"); +%feature("doxygen:ignore:compileroptions", range="line"); +%feature("doxygen:ignore:forcpponly", range="end"); + +#ifdef SWIGJAVA +%feature("doxygen:ignore:beginJavaOnly", range="end:endJavaOnly", contents="parse"); +%feature("doxygen:ignore:beginPythonOnly", range="end:endPythonOnly"); +#elif defined(SWIGPYTHON) +%feature("doxygen:ignore:beginJavaOnly", range="end:endJavaOnly"); +%feature("doxygen:ignore:beginPythonOnly", range="end:endPythonOnly", contents="parse"); +#else +%feature("doxygen:ignore:beginJavaOnly", range="end:endJavaOnly"); +%feature("doxygen:ignore:beginPythonOnly", range="end:endPythonOnly"); +#endif + +%inline %{ + +/** + A contrived example of ignoring too many commands in one comment. + + @forcpponly + This is C++-specific. + @endforcpponly + + @beginJavaOnly + This is specific to @e Java. + @endJavaOnly + + @beginPythonOnly + This is specific to @b Python. + @endPythonOnly + + @transferfull Command ignored, but anything here is still included. + + @compileroptions This function must be compiled with /EHa when using MSVC. + */ +int * func() { return 0; } + +%} diff --git a/Examples/test-suite/doxygen_misc_constructs.h b/Examples/test-suite/doxygen_misc_constructs.h new file mode 100644 index 000000000..d677dc3d3 --- /dev/null +++ b/Examples/test-suite/doxygen_misc_constructs.h @@ -0,0 +1,94 @@ +/* + * This file contains comments which demonstrate details about Doxygen processing, + * so they can be emulated in SWIG doxy comment translation + */ + + + +/**This comment without space after '*' is valid in Doxygen. + * + */ +void isNoSpaceValidA() +{} + +/**.This comment without space after '*' is valid in Doxygen. + * + */ +void isNoSpaceValidB() +{} + + +/***This is not Doxygen comment. + * + */ +void isNoSpaceValidC() +{} + + +/** + * Backslash following\c word is a valid doxygen command. Output contains + * 'followingword' with 'word' in code font. + */ +void backslashA() +{} + +// Output of escaped symbols below in doxygen generated HTML: +// Rendered: Escaped symbols: $ @ \ & < > # % " \. :: @text ::text +// HTML source: Escaped symbols: $ @ \ & < > # % " \. :: @text ::text + + +/** + * Doxy command without trailing \cspace space is ignored - nothing appears + * on output. Standalone \ and '\' get to output. + * Standalone @ and '@' get to output. + * Commands "in quoted \b strings are treated as plain text". + * Commands not recognized by Doxygen \blah @blah are ignored. + * Backslashes in DOS paths d:\xyz\qwe\myfile and words + * following them do not appear on output, we must quote them with + * double quotes: "d:\xyz\qwe\myfile", "@something". Single quotes do not help: + * 'd:\xyz\qwe\myfile'. Escaping works: d:\\xyz\\qwe\\myfile. Unix + * paths of course have no such problems: /xyz/qwe/myfile + * Commands for escaped symbols: + * \$ \@ \\ \& \~ \< \> \# \% \" \. \:: \@text \::text + */ +void backslashB() +{} + +/** + * Backslash e at end of \e line froze SWIG \e + * with old comment parser. + * + * @see MyClass::fun(char, + * float) + */ +void backslashC() +{} + +/** + * The next line contains expression: + *
    + * ['retVal < 10', 'g_counter == 23 && g_mode & 3']
    + *
    + * + * Both words should be emphasized \b isystem.connect. + * But not the last period. For \b example, comma should not be emphasized. + * Similar \b for: double colon. + * + * Spaces at the start of line should be taken into account: + * @param id used as prefix in log + * statements. The default value is empty string, which is OK if + * there is only one app. instance. Example: + *
    + *         ctrl.setBP("func1");
    + *     
    + * If we set the id to \c main_, we get: + *
    + *         main_ctrl.setBP("func1");
    + *     
    + * + * @param fileName name of the log file + */ +void cycle(int id, char *fileName) +{} + + diff --git a/Examples/test-suite/doxygen_misc_constructs.i b/Examples/test-suite/doxygen_misc_constructs.i new file mode 100644 index 000000000..c1b3eea31 --- /dev/null +++ b/Examples/test-suite/doxygen_misc_constructs.i @@ -0,0 +1,127 @@ +// This file contains tests for situations, which do not normally +// appear in the code, but must nevertheless be handled correctly. + +%module doxygen_misc_constructs + +%warnfilter(SWIGWARN_DOXYGEN_UNKNOWN_COMMAND) backslashB; + +%inline %{ + + // Tag '@endink' must be recognized even if it is not + // followed by whitespace. + + /** Tag endlink must be recognized also when followed by nonspace character. + * + * @link Connection::getId() @endlink
    */ + + char g_counter; + + + /** + Tag endlink must be recognized also when it is the last token + in the comment. + + @link Connection::getId() @endlink
    + @link debugIdeTraceProfilerCoverageSample.py Python example. @endlink + */ + int g_zipCode; + + + // Parameter 'isReportSize' must appear in comment of the overload, which + // has it. Empty line before link must be preserved. + /** + * Returns address of file line. + * + * @param fileName name of the file, where the source line is located + * @param line line number + * @param isGetSize if set, for every object location both address and size are returned + * + * @link Connection::getId() @endlink
    + */ + void getAddress(int &fileName, + int line, + bool isGetSize = false) {} + + // The first comment must be ignored. + /** + * \defgroup icFacade isystem.connect Facade + * + * This page shows the core classes, which can be used to control + * all aspects of winIDEA, for example: debugging, analyzers, IO module, ... + */ + + /** + * This class contains information for connection to winIDEA. Its methods + * return reference to self, so we can use it like this: + *
    +     * CConnectionConfig config = new CConnectionConfig();
    +     * config.discoveryPort(5534).dllPath("C:\\myWinIDEA\\connect.dll").id("main");
    +     * 
    + * + * All parameters are optional. Set only what is required, default values are + * used for unspecified parameters. + *

    + * + * @link advancedWinIDEALaunching.py Python example.@endlink
    + */ + class CConnectionConfig + { + }; + + // Text after '\c' must be kept unchanged in Python. + /** + * Determines how long the \c isystem.connect should wait for running + * instances to respond. Only one of \c lfWaitXXX flags from IConnect::ELaunchFlags + * may be specified. + */ + int waitTime(long waitTime) {return 33;} + + + // Line with tag \ingroup must not appear in translated comment: + /** \ingroup icFacade + * + * This function returns connection id. + */ + int getConnection() {return 3;} + + // the following must produce no comment in wrapper + /*******************************************************************/ + char getFirstLetter() {return 'a';} + + + /** + * Class description. + */ + class ClassWithNestedEnum { + public: + /** + * Enum description. + */ + typedef enum {ONE, ///< desc of one + TWO, ///< desc of two + THREE ///< desc of three + } ENested; + + }; + + /// @return This is a bad place for this tag, but it should be ignored. + struct StructWithReturnComment {}; + + /** + An example of a list in a documentation comment. + + - The first item of the list. + - The second list item, on + several indented lines, + showing that the indentation + is preserved. + - And the final list item after it. + + And this is not a list item any more. + */ + void showList() { } + + #include "doxygen_misc_constructs.h" + +%} + %include "doxygen_misc_constructs.h" diff --git a/Examples/test-suite/doxygen_nested_class.i b/Examples/test-suite/doxygen_nested_class.i new file mode 100644 index 000000000..55575e34f --- /dev/null +++ b/Examples/test-suite/doxygen_nested_class.i @@ -0,0 +1,24 @@ +%module doxygen_nested_class + +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) DoxOuter::DoxInner; + +%inline %{ + +struct DoxOuter { + /** DoxOuter constructor */ + DoxOuter() {} + /** DoxInner class description */ + struct DoxInner { + /** DoxInner constructor */ + DoxInner() {} + /** doxInt variable */ + int doxInt; + /** doxShort const variable */ + static const short doxShort = 1; + /** doxMethod description */ + void doxMethod() {} + /** doxStaticMethod description */ + static void doxStaticMethod() {} + }; +}; +%} diff --git a/Examples/test-suite/doxygen_parsing.i b/Examples/test-suite/doxygen_parsing.i new file mode 100644 index 000000000..40f37a4c2 --- /dev/null +++ b/Examples/test-suite/doxygen_parsing.i @@ -0,0 +1,140 @@ +%module doxygen_parsing + +%inline %{ + +/** + * The class comment + */ +class SomeClass +{ +}; + +/** + * The function comment + */ +void someFunction() +{ +} + +/** + * The enum comment + */ +enum SomeEnum +{ + SOME_ENUM_ITEM +}; + +/** + * The struct comment + */ +struct SomeStruct +{ +}; + +/** + * The var comment + */ +int someVar=42; + +/** + * The constant comment + */ +#define CONSTANT_VALUE 4242 + +/// SomeAnotherClass description +class SomeAnotherClass +{ +public: + /// First overloaded constructor. + SomeAnotherClass(int) { } + + /// Second overloaded constructor. + SomeAnotherClass(const char*) { } + + + /** + * The class attribute comment + */ + int classAttr; + + int classAttr2; ///< The class attribute post-comment + + int classAttr3; ///< The class attribute post-comment + //!< with details + + /** + * The class method comment. + * + * \link SomeAnotherClass#classMethodExtended(int, int) a link text \endlink + */ + void classMethod() + { + } + + /** + * The class method with parameter + */ + void classMethodExtended( + int a, ///< Parameter a + int b ///< Parameter b + ) + { + } + + /** + * The class method with parameter + * + * @param a Parameter a + * @param b Parameter b + */ + void classMethodExtended2(int a, int b) + { + } +}; + +struct SomeAnotherStruct +{ + /** + * The struct attribute comment + */ + int structAttr; + + int structAttr2; ///< The struct attribute post-comment + + int structAttr3; ///< The struct attribute post-comment + //!< with details + + /** + * The struct method comment + */ + void structMethod() + { + } + + /** + * The struct method with parameter + */ + void structMethodExtended( + int a, ///< Parameter a + int b ///< Parameter b + ) + { + } + + /** + * The struct method with parameter + * + * @param a Parameter a + * @param b Parameter b + */ + void structMethodExtended2(int a, int b) + { + } +}; + +#ifdef SWIGPYTHON_BUILTIN +bool is_python_builtin() { return true; } +#else +bool is_python_builtin() { return false; } +#endif +%} diff --git a/Examples/test-suite/doxygen_parsing_enums.i b/Examples/test-suite/doxygen_parsing_enums.i new file mode 100644 index 000000000..b7a39871f --- /dev/null +++ b/Examples/test-suite/doxygen_parsing_enums.i @@ -0,0 +1,40 @@ +%module doxygen_parsing_enums + +%inline %{ + + + /** + * Testing comments before enum items + */ + enum SomeAnotherEnum + { + /** + * The comment for the first item + */ + SOME_ITEM_1, + /** + * The comment for the second item + */ + SOME_ITEM_2, + /** + * The comment for the third item + */ + SOME_ITEM_3 + }; + + /** + * Testing comments after enum items + */ + enum SomeAnotherEnum2 + { + SOME_ITEM_10, ///< Post comment for the first item + SOME_ITEM_20, ///< Post comment for the second item + SOME_ITEM_30 ///< Post comment for the third item + }; + + enum SomeEnumWithTrailingComma + { + SOME_ITEM_100, ///< Post comment after comma. + SOME_ITEM_200, ///< Post comment after last comma. + }; +%} diff --git a/Examples/test-suite/doxygen_parsing_enums_proper.i b/Examples/test-suite/doxygen_parsing_enums_proper.i new file mode 100644 index 000000000..1a69a84f1 --- /dev/null +++ b/Examples/test-suite/doxygen_parsing_enums_proper.i @@ -0,0 +1,7 @@ +%module "doxygen_parsing_enums_proper" + +// Test enum commenting using the proper enums in the target language +%include "enums.swg" + +%include "doxygen_parsing_enums.i" + diff --git a/Examples/test-suite/doxygen_parsing_enums_simple.i b/Examples/test-suite/doxygen_parsing_enums_simple.i new file mode 100644 index 000000000..823a27584 --- /dev/null +++ b/Examples/test-suite/doxygen_parsing_enums_simple.i @@ -0,0 +1,6 @@ +%module "doxygen_parsing_enums_simple" + +// Test enum commenting using simple constants (SWIG-1.3.21 and earlier default enum wrapping for C# and Java) +%include "enumsimple.swg" + +%include "doxygen_parsing_enums.i" \ No newline at end of file diff --git a/Examples/test-suite/doxygen_parsing_enums_typesafe.i b/Examples/test-suite/doxygen_parsing_enums_typesafe.i new file mode 100644 index 000000000..25e355ee2 --- /dev/null +++ b/Examples/test-suite/doxygen_parsing_enums_typesafe.i @@ -0,0 +1,8 @@ +%module "doxygen_parsing_enums_typesafe" + +// Test enum commenting using the typesafe enum pattern in the target language +%include "enumtypesafe.swg" + +#define SWIG_TEST_NOCSCONST // For C# typesafe enums + +%include "doxygen_parsing_enums.i" \ No newline at end of file diff --git a/Examples/test-suite/doxygen_parsing_enums_typeunsafe.i b/Examples/test-suite/doxygen_parsing_enums_typeunsafe.i new file mode 100644 index 000000000..e001035df --- /dev/null +++ b/Examples/test-suite/doxygen_parsing_enums_typeunsafe.i @@ -0,0 +1,6 @@ +%module "doxygen_parsing_enums_typeunsafe" + +// Test enum commenting using a type unsafe enum pattern (constant integers in a class for the enum type) +%include "enumtypeunsafe.swg" + +%include "doxygen_parsing_enums.i" \ No newline at end of file diff --git a/Examples/test-suite/doxygen_translate.i b/Examples/test-suite/doxygen_translate.i new file mode 100644 index 000000000..bb0af1c14 --- /dev/null +++ b/Examples/test-suite/doxygen_translate.i @@ -0,0 +1,266 @@ +%module doxygen_translate + +#if defined(SWIGJAVA) +%javamethodmodifiers function "@Deprecated\npublic" +#endif + +%inline %{ + +/** + * \a Hello + * + * \arg some list item + * + * \authors lots of them + * + * \author Zubr + * + * \b boldword + * + * \c codeword + * + * \cite citationword + * + * \code some test code \endcode + * + * \cond SOMECONDITION + * Some conditional comment + * \endcond + * + * \copyright some copyright + * + * \deprecated Now use another function + * + * \e italicword + * + * \example someFile.txt + * Some details on using the example + * + * \exception SuperError + * + * \if ANOTHERCONDITION + * First part of comment + * \if SECONDCONDITION + * Nested condition text + * \elseif THIRDCONDITION + * The third condition text + * \else + * The last text block + * \endif + * \else + * Second part of comment + * \if CONDITION + * Second part extended + * \endif + * \endif + * + * \ifnot SOMECONDITION + * This is printed if not + * \endif + * + * \image html testImage.bmp "Hello, world!" width=10cm + * + *

      + * + * \li Some unordered list + * \li With lots of items + * \li lots of lots of items + * + *
    + * + * \link someMember Some description follows \endlink + * + * \n \n \n + * + * \note Here + * is the note! + * + * \overload + * + * \p someword + * + * \package superPackage + * + * \par The paragraph title + * The paragraph text. + * Maybe even multiline + * + * \param a the first param + * + * \remark Some remark text + * + * \remarks Another remarks section + * + * \result Whatever + * + * \return it + * + * \returns may return + * + * \sa someOtherMethod + * + * \see function + * + * \since version 0.0.0.1 + * + * \throw superException + * + * \throws RuntimeError + * + * \todo Some very important task + * + * \tparam b B is mentioned again... + * + * \verbatim + * very long + * text with tags + * \endverbatim + * + * \version 0.0.0.2 + * + * \warning This is senseless! + * + * Here goes test of symbols: + * \$ \@ \\ \& \~ \< \> \# \% \" \. \:: + * + * And here goes simple text + */ +int function(int a, float b) +{ + return 0; +} + +/** + * Test for html tags. See Doxygen doc for list of tags recognized by Doxygen. + * + *
    This is link + * bold + *
    + * Quotation block. + *
    + *
    + *
    center
    + * this is code + * + *
    + *
    Starts an item title.
    + *
    Starts an item description.
    + *
    + * + * Starts a piece of text displayed in a typewriter font. + * + *
    Starts a section with a specific style (HTML only) + *
    + * Starts a piece of text displayed in an italic font. + * + *
    'Form' does not generate any output. + *
    + *
    + *

    Heading 1 + *

    + *

    Heading 2 + *

    + *

    Heading 3 + *

    + * Starts a piece of text displayed in an italic font. + * Input tag. + * + * Meta tag. + * Multicol is ignored by doxygen. + * + * + *
      + *
    1. List item 1.
    2. + *
    3. List item 2.
    4. + *
    + * + *

    Starts a new paragraph. + *

    + *
    Starts a preformatted fragment.
    + * 
    + * Starts a section of text displayed in a smaller font. + * + * Starts an inline text fragment with a specific style. + * Starts a section of bold text. + * Starts a piece of text displayed in subscript. + * Starts a piece of text displayed in superscript. + * + * + * + * + * + * + * + *
    Animals
    Column 1 Column 2
    cow dog
    cat mouse
    horse parrot
    + * + * Starts a piece of text displayed in a typewriter font. + * + * Starts a piece of text displayed in a typewriter font. + * + * + *
      + *
    • List item 1.
    • + *
    • List item 2.
    • + *
    • List item 3.
    • + *
    + * + * Starts a piece of text displayed in an italic font. + * + * \htmlonly + * underlined \b bold text - doxy commands are ignored inside 'htmlonly' section + * \endhtmlonly + */ +void htmlFunction(int a, float b) +{ +} + +/** + * The meaning of flags: + * + * @param byFlags bits marking required items: + * + * + * + * + * + *
    Size in bits Items Required
    1 - 8 1
    9 - 16 2
    17 - 32 4
    + * Almost all combinations of above flags are supported by + * \c htmlTable... functions. + */ +void htmlTableFunction(int byFlags) +{ +} + + +/** + * All entities are treated as commands © ™ ® + * should work also<in text + * > + * & + * ' + * " + * ‘ + * ’ + * “ + * ” + * – + * — + *   + * × + * − + * ⋅ + * ∼ + * ≤ + * ≥ + * ← + * → + * Not an &text; html entity - ignored by Doxygen. + * Not an &text html entity - ampersand is replaced with entity. + */ +void htmlEntitiesFunction(int a, float b) +{ +} + + + +%} diff --git a/Examples/test-suite/doxygen_translate_all_tags.i b/Examples/test-suite/doxygen_translate_all_tags.i new file mode 100644 index 000000000..8da683d52 --- /dev/null +++ b/Examples/test-suite/doxygen_translate_all_tags.i @@ -0,0 +1,413 @@ +%module doxygen_translate_all_tags + +#if defined(SWIGJAVA) +%javamethodmodifiers func02 "@Deprecated\npublic" +#endif + +%inline %{ + +/** + * \a Hello + * + * \addindex SomeLatexIndex + * + * \addtogroup someGroup "Some title" + * + * \anchor theAnchor + * + * \arg some list item + * + * \attention This is attention! + * You were warned! + * + * \authors lots of them + * \author Zubr + * + * \b boldword + * + * \brief Some brief description, + * extended to many lines. + * + * \bug Not everything works right now... + * \c codeword + * + * \callgraph + * \callergraph + * \category someCategory headerFile.h headerName + * + * \cite citationword + * \class someClass headerFile.h headerName + * \code some test code \endcode + * + * Code immediately following text. Pydoc translation must add an + * empty line before: + * \code more test code \endcode + */ +void func01(int a) +{ +} + + +/** + * \cond SOMECONDITION + * Some conditional comment + * \endcond + * + * \copybrief someClass::someMethod + * + * \copydetails someClass::someMethod2 + * + * \copydoc someClass::someMethod3 + * + * \copyright some copyright + * + * \date 1970 - 2012 + * + * \def someDefine + * + * \defgroup someGroup Some titles + * + * \deprecated Now use another function + * + * \details This is very large + * and detailed description of some thing + */ +void func02(int a) +{ +} + + +/** + * Comment for \b func03(). + * + * \dir /somePath/someFolder + * + * \dontinclude someFile.h + * + * \dot + * digraph example { + * node [shape=record, fontname=Helvetica, fontsize=10]; + * b [ label="class B" URL="\ref B"]; + * c [ label="class C" URL="\ref C"]; + * b -> c [ arrowhead="open", style="dashed" ]; + * } + * \enddot + * + * \dotfile dotFile.dot "The caption" + * + * \e italicword + * + * \em emphazedWord + * + * \enum someEnum + * + * \example someFile.txt + * Some details on using the example + */ +void func03(int a) +{ +} + + +/** + * + * \exception SuperError + * + * \extends someOtherFunction + * + * \f$ \sqrt{(x_2-x_1)^2+(y_2-y_1)^2} \f$ + * + * \f[ + * \sqrt{(x_2-x_1)^2+(y_2-y_1)^2} + * \f] + * + * \f{ + * \sqrt{(x_2-x_1)^2+(y_2-y_1)^2} + * \f} + * + * Math immediately following text. Pydoc translation must add an + * empty line before: + * \f[ + * \sqrt{(x_2-x_1)^2+(y_2-y_1)^2} + * \f] + * + * \file file.h + * + * \fn someFn + * + * \headerfile someHeader.h "Header name" + * + * \hideinitializer + * + * \htmlinclude htmlFile.htm + * + * \htmlonly + * This will only appear in hmtl + * \endhtmlonly + */ +void func04(int a) +{ +} + + +/** + * \if ANOTHERCONDITION + * First part of comment + * \if SECONDCONDITION + * Nested condition text + * \elseif THIRDCONDITION + * The third condition text + * \else + * The last text block + * \endif + * \else + * Second part of comment + * \if CONDITION + * Second part extended + * \endif + * \endif + * + * \ifnot SOMECONDITION + * This is printed if not + * \endif + * + * \image html testImage.bmp "Hello, world!" asd=10qwe + * + * \implements someFunction + * + * \include header.h + * + * \includelineno header2.h + * + * \ingroup someGroup anotherGroup + * + * \internal + * + * \invariant Some text + * describing invariant. + */ +void func05(int a) +{ +} + + +/** + * Comment for \b func06(). + * + * \interface someInterface someHeader.h "Header name" + * + * \latexonly + * This will only appear in LATeX + * \endlatexonly + * + *
      + * + * \li Some unordered list + * \li With lots of items + * \li lots of lots of items + * + *
    + * + * \line example + * + * \link someMember Some description follows \endlink + * + * \mainpage Some title + * + * \manonly + * This will only appear in man + * \endmanonly + * + * \memberof someThing + * + * \msc + * Sender,Receiver; + * Sender->Receiver [label="Command()", URL="\ref Receiver::Command()"]; + * Sender<-Receiver [label="Ack()", URL="\ref Ack()", ID="1"]; + * \endmsc + * + * \mscfile mscFile.msc "The caption" + * + * \n \n \n + */ +void func06(int a) +{ +} + + +/** + * Comment for \b func07(). + * + * \name someHeader.h + * + * \namespace someNamespace + * + * \nosubgrouping + * + * \note Here + * is the note! + * + * \overload + * + * \p someword + * + * \package superPackage + * + * \page somePage The title + * + * \par The paragraph title + * The paragraph text. + * Maybe even multiline + * + * \paragraph someParagraph Paragraph title + * + * \param a the first param + * + * \post Some description + * + * \pre Some description + * + * \private + * + * \privatesection + * + * \property someVar + */ +void func07(int a) +{ +} + + +/** + * \protected + * + * \protectedsection + * + * \anchor someAnchor + * Text after anchor. + * \protocol someProtocol header.h "Header name" + * + * \public + * + * \publicsection + * + * \ref someAnchor "Anchor description" + * + * \ref someAnchor not quoted text is not part of ref tag + * + * \ref someAnchor + * + * \related toSomething + * + * \relates toSomethingElse + * + * \relatedalso someName + * + * \relatesalso someName + * + * \remark Some remark text + * + * \remarks Another remarks section + * + * \result Whatever + * + * \return it + * + * \returns may return + * + * \retval someValue Some description + */ +void func08(int a) +{ +} + + +/** + * \rtfonly + * This will only appear in RTF + * \endrtfonly + * + * \sa someOtherMethod + * + * \section someSection Some title + * + * \see function + * + * \short Same as + * brief description + * + * \showinitializer + * + * \since version 0.0.0.1 + * + * \skip somePattern + * + * \skipline someLine + * + * \snippet example.h Some snippet + * + * \struct someStruct + * + * \subpage someSubpage "Some description" + * + * \subsection someSubsection Some title + * + * \subsubsection someSubsection Some title + * + * \tableofcontents + * + * \test Some + * description of the + * test case + * + * \throw superException + * + * \throws RuntimeError + */ +void func09(int a) +{ +} + + +/** + * \todo Some very important task + * + * \tparam b B is mentioned again... + * + * \typedef someTypedef + * + * \union someUnion + * + * \until somePattern + * + * \var someVar + * + * \verbatim + * very long + * text with tags + * \endverbatim + * + * \verbinclude someFile.h + * + * \version 0.0.0.2 + * + * \warning This is senseless! + * + * \weakgroup someGroup Some title + * + * \xmlonly + * This will only appear in XML + * \endxmlonly + * + * \xrefitem todo "Todo" "Todo List" + * + * Here goes test of symbols: + * \$ \@ \\ \& \~ \< \> \# \% \" \. \:: + * + * And here goes simple text + */ +void func10(int a, float b) +{ +} + +%} diff --git a/Examples/test-suite/doxygen_translate_links.i b/Examples/test-suite/doxygen_translate_links.i new file mode 100644 index 000000000..769a4f4e7 --- /dev/null +++ b/Examples/test-suite/doxygen_translate_links.i @@ -0,0 +1,67 @@ + + +%module doxygen_translate_links +%include "std_string.i" + +%inline %{ + +class Shape +{ +public: + typedef Shape* superType; +}; + +/** + * Testing typenames converting in \@ link + * + * \link superFunc(int,std::string) + * Test for std_string member + * \endlink + * + * \link superFunc(int,long,void*) + * Test for simple types + * \endlink + * + * \link superFunc(Shape::superType*) + * Test for custom types + * \endlink + * + * \link superFunc(int**[13]) + * Test for complex types + * \endlink + * + * same works for 'See also:' links: + * + * \sa superFunc(int,std::string) + * \sa superFunc(int,long,void*) + * \sa superFunc(Shape::superType*) + * \sa superFunc(int**[13]) + * + * some failing params: + * + * \sa superFunc() + * \sa superFunc() + * \sa superFunc() + * + */ +void function() +{ +} + +void superFunc(int, std::string) +{ +} + +void superFunc(int, long, void *) +{ +} + +void superFunc(Shape::superType *) +{ +} + +void superFunc(int **arr[13]) +{ +} + +%} diff --git a/Examples/test-suite/enum_macro.i b/Examples/test-suite/enum_macro.i index c058cdf72..a5e8a2461 100644 --- a/Examples/test-suite/enum_macro.i +++ b/Examples/test-suite/enum_macro.i @@ -97,3 +97,45 @@ enum Greeks13 #define GREEK13 -13 }; +/* Multiple macros */ + +%inline %{ +enum Greeks14 +{ +#define GREEK14a -14 +#define GREEK14b -140 + theta14, +}; + +enum Greeks15 +{ + alpha15 = 150, + beta15 = 151, +#define GREEK15a -150 +#define GREEK15b -151 + theta15 = 152, + delta15 = 153 +}; + +enum Greeks16 +{ + alpha16 = 160, + beta16 = 161, +#define GREEK16a -160 +#define GREEK16b -161 +#define GREEK16c -162 + theta16 = 162, + delta16 = 163 +}; + +enum Greeks17 +{ + alpha17 = 170, + beta17 = 171, + theta17 = 172, + delta17 = 173 +#define GREEK17a -170 +#define GREEK17b -171 +#define GREEK17c -172 +}; +%} diff --git a/Examples/test-suite/enum_thorough.i b/Examples/test-suite/enum_thorough.i index fd5978102..3beefccc0 100644 --- a/Examples/test-suite/enum_thorough.i +++ b/Examples/test-suite/enum_thorough.i @@ -569,6 +569,17 @@ repeat repeatTest(repeat e) { return e; } } %} +%inline %{ +namespace EnumWithMacro { +#define PACK(C1,C2,C3,C4) ((C1<<24)|(C2<<16)|(C3<<8)|C4) +typedef enum { + ABCD = PACK('A','B','C','D'), + ABCD2 = ABCD +} enumWithMacro; +enumWithMacro enumWithMacroTest(enumWithMacro e) { return e; } +} +%} + %inline %{ namespace DifferentSpace { enum DifferentTypes { @@ -577,7 +588,9 @@ enum DifferentTypes { typebooltrue = true, typebooltwo, typechar = 'C', - typedefaultint + typedefaultint, + typecharcompound='A'+1, + typecharcompound2='B' << 2 }; DifferentTypes differentTypesTest(DifferentTypes n) { return n; } @@ -587,7 +600,9 @@ enum { global_typebooltrue = true, global_typebooltwo, global_typechar = 'C', - global_typedefaultint + global_typedefaultint, + global_typecharcompound='A'+1, + global_typecharcompound2='B' << 2 }; int globalDifferentTypesTest(int n) { return n; } } diff --git a/Examples/test-suite/errors/Makefile.in b/Examples/test-suite/errors/Makefile.in index cf7889a1d..10e5bdd8f 100644 --- a/Examples/test-suite/errors/Makefile.in +++ b/Examples/test-suite/errors/Makefile.in @@ -24,15 +24,27 @@ SWIG_LIB_SET = @SWIG_LIB_SET@ SWIGINVOKE = $(SWIG_LIB_SET) $(SWIGTOOL) $(SWIGEXE) # All .i files with prefix 'cpp_' will be treated as C++ input and remaining .i files as C input -ALL_ERROR_TEST_CASES := $(patsubst %.i,%, $(notdir $(wildcard $(srcdir)/*.i))) -CPP_ERROR_TEST_CASES := $(filter cpp_%, $(ALL_ERROR_TEST_CASES)) -C_ERROR_TEST_CASES := $(filter-out $(CPP_ERROR_TEST_CASES), $(ALL_ERROR_TEST_CASES)) +ALL_ERROR_TEST_CASES := $(sort $(patsubst %.i,%, $(notdir $(wildcard $(srcdir)/*.i)))) +CPP_ERROR_TEST_CASES := $(sort $(filter cpp_%, $(ALL_ERROR_TEST_CASES))) +C_ERROR_TEST_CASES := $(sort $(filter-out $(CPP_ERROR_TEST_CASES), $(ALL_ERROR_TEST_CASES))) +DOXYGEN_ERROR_TEST_CASES := $(sort $(filter doxygen_%, $(C_ERROR_TEST_CASES))) +C_ERROR_TEST_CASES := $(sort $(filter-out $(DOXYGEN_ERROR_TEST_CASES), $(C_ERROR_TEST_CASES))) + +# Always use C++ for Doxygen tests, there doesn't seem to be any need to +# distinguish between C and C++ Doxygen tests. +DOXYGEN_ERROR_TEST_CASES := $(DOXYGEN_ERROR_TEST_CASES:=.cpptest) ERROR_TEST_CASES := $(CPP_ERROR_TEST_CASES:=.cpptest) \ - $(C_ERROR_TEST_CASES:=.ctest) + $(C_ERROR_TEST_CASES:=.ctest) \ + $(DOXYGEN_ERROR_TEST_CASES) include $(srcdir)/../common.mk +# This is tricky: we need to let common.mk define SWIGOPT before appending to +# it, if we do it before including it, its defining of SWIGOPT would override +# whatever we do here. +$(DOXYGEN_ERROR_TEST_CASES): SWIGOPT += -doxygen + # Portable dos2unix / todos for stripping CR TODOS = tr -d '\r' #TODOS = sed -e 's/\r$$//' # On Mac OS X behaves as if written 's/r$$//' diff --git a/Examples/test-suite/errors/cpp_bad_global_memberptr.i b/Examples/test-suite/errors/cpp_bad_global_memberptr.i new file mode 100644 index 000000000..f0d95cfed --- /dev/null +++ b/Examples/test-suite/errors/cpp_bad_global_memberptr.i @@ -0,0 +1,6 @@ +%module xxx + +struct Funcs {}; + +short (Funcs::* *)(bool) = 0; +short (Funcs::* const*)(bool) = 0; diff --git a/Examples/test-suite/errors/cpp_bad_global_memberptr.stderr b/Examples/test-suite/errors/cpp_bad_global_memberptr.stderr new file mode 100644 index 000000000..ac3f9cbe0 --- /dev/null +++ b/Examples/test-suite/errors/cpp_bad_global_memberptr.stderr @@ -0,0 +1,2 @@ +cpp_bad_global_memberptr.i:5: Error: Missing symbol name for global declaration +cpp_bad_global_memberptr.i:6: Error: Missing symbol name for global declaration diff --git a/Examples/test-suite/errors/cpp_class_definition.i b/Examples/test-suite/errors/cpp_class_definition.i new file mode 100644 index 000000000..8381e75cc --- /dev/null +++ b/Examples/test-suite/errors/cpp_class_definition.i @@ -0,0 +1,26 @@ +%module xxx + +// This should error but doesn't +#if 0 +namespace OtherSpace { + struct L; +} +namespace Space11 { + namespace SubSpace11 { + using OtherSpace::L; + struct L { + void ll(); + }; + } +} +#endif + +namespace Space1 { + struct A; +} +namespace Space2 { + struct Space1::A { + void x(); + }; +} + diff --git a/Examples/test-suite/errors/cpp_class_definition.stderr b/Examples/test-suite/errors/cpp_class_definition.stderr new file mode 100644 index 000000000..2c4102842 --- /dev/null +++ b/Examples/test-suite/errors/cpp_class_definition.stderr @@ -0,0 +1 @@ +cpp_class_definition.i:22: Error: 'Space1::A' resolves to 'Space1::A' and was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'. diff --git a/Examples/test-suite/errors/cpp_final_destructor.stderr b/Examples/test-suite/errors/cpp_final_destructor.stderr new file mode 100644 index 000000000..d8c509d0c --- /dev/null +++ b/Examples/test-suite/errors/cpp_final_destructor.stderr @@ -0,0 +1 @@ +cpp_final_destructor.i:7: Warning 525: Destructor BaseFinal::~BaseFinal() is final, BaseFinal cannot be a director class. diff --git a/Examples/test-suite/errors/cpp_invalid_exponents1.i b/Examples/test-suite/errors/cpp_invalid_exponents1.i new file mode 100644 index 000000000..1ff2c3603 --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_exponents1.i @@ -0,0 +1,4 @@ +%module xxx + +void bad(double nn = 5e); + diff --git a/Examples/test-suite/errors/cpp_invalid_exponents1.stderr b/Examples/test-suite/errors/cpp_invalid_exponents1.stderr new file mode 100644 index 000000000..6096114be --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_exponents1.stderr @@ -0,0 +1,2 @@ +cpp_invalid_exponents1.i:3: Error: Exponent does not have any digits +cpp_invalid_exponents1.i:3: Error: Syntax error in input(1). diff --git a/Examples/test-suite/errors/cpp_invalid_exponents2.i b/Examples/test-suite/errors/cpp_invalid_exponents2.i new file mode 100644 index 000000000..2e074872a --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_exponents2.i @@ -0,0 +1,4 @@ +%module xxx + +void bad(double nn = 6.6e); + diff --git a/Examples/test-suite/errors/cpp_invalid_exponents2.stderr b/Examples/test-suite/errors/cpp_invalid_exponents2.stderr new file mode 100644 index 000000000..e7d1bf07d --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_exponents2.stderr @@ -0,0 +1,2 @@ +cpp_invalid_exponents2.i:3: Error: Exponent does not have any digits +cpp_invalid_exponents2.i:3: Error: Syntax error in input(1). diff --git a/Examples/test-suite/errors/cpp_invalid_qualifiers.i b/Examples/test-suite/errors/cpp_invalid_qualifiers.i new file mode 100644 index 000000000..fd3b36332 --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_qualifiers.i @@ -0,0 +1,43 @@ +%module cpp_invalid_qualifiers + +// Constructors, destructors and static methods cannot have qualifiers +struct A { + ~A() const; +}; +struct B { + virtual ~B() const; +}; +struct C { + ~C() &; +}; +struct D { + virtual ~D() &; +}; +struct E { + ~E() &&; +}; +struct F { + virtual ~F() &&; +}; + +struct J { + J() const; + J(int) const; +}; +struct K { + K() &; + K(int) &; +}; +struct L { + L() &&; + L(int) &&; +}; + +struct M { + static void m1() const; + static void m2() &; + thread_local static void m3() &&; + static auto m4() const -> int; + static auto m5() & -> int; + static auto m6() && -> int; +}; diff --git a/Examples/test-suite/errors/cpp_invalid_qualifiers.stderr b/Examples/test-suite/errors/cpp_invalid_qualifiers.stderr new file mode 100644 index 000000000..7b3e442eb --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_qualifiers.stderr @@ -0,0 +1,20 @@ +cpp_invalid_qualifiers.i:5: Error: Destructor ~A() const cannot have a qualifier. +cpp_invalid_qualifiers.i:8: Error: Destructor ~B() const cannot have a qualifier. +cpp_invalid_qualifiers.i:11: Error: Destructor ~C() & cannot have a qualifier. +cpp_invalid_qualifiers.i:14: Error: Destructor ~D() & cannot have a qualifier. +cpp_invalid_qualifiers.i:17: Error: Destructor ~E() && cannot have a qualifier. +cpp_invalid_qualifiers.i:20: Error: Destructor ~F() && cannot have a qualifier. +cpp_invalid_qualifiers.i:24: Error: Constructor cannot have a qualifier. +cpp_invalid_qualifiers.i:25: Error: Constructor cannot have a qualifier. +cpp_invalid_qualifiers.i:28: Error: Constructor cannot have a qualifier. +cpp_invalid_qualifiers.i:29: Error: Constructor cannot have a qualifier. +cpp_invalid_qualifiers.i:32: Error: Constructor cannot have a qualifier. +cpp_invalid_qualifiers.i:33: Error: Constructor cannot have a qualifier. +cpp_invalid_qualifiers.i:37: Error: Static function m1() const cannot have a qualifier. +cpp_invalid_qualifiers.i:38: Error: Static function m2() & cannot have a qualifier. +cpp_invalid_qualifiers.i:39: Error: Static function m3() && cannot have a qualifier. +cpp_invalid_qualifiers.i:39: Warning 405: Method with rvalue ref-qualifier m3() && ignored. +cpp_invalid_qualifiers.i:40: Error: Static function m4() const cannot have a qualifier. +cpp_invalid_qualifiers.i:41: Error: Static function m5() & cannot have a qualifier. +cpp_invalid_qualifiers.i:42: Error: Static function m6() && cannot have a qualifier. +cpp_invalid_qualifiers.i:42: Warning 405: Method with rvalue ref-qualifier m6() && ignored. diff --git a/Examples/test-suite/errors/cpp_invalid_template.i b/Examples/test-suite/errors/cpp_invalid_template.i new file mode 100644 index 000000000..ea0d7beac --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_template.i @@ -0,0 +1,9 @@ +%module cpp_invalid_scope + +%template(abc) SSS::AAA; + +namespace UUU { + struct JJJ; +} + +%template(xxx) UUU::JJJ; diff --git a/Examples/test-suite/errors/cpp_invalid_template.stderr b/Examples/test-suite/errors/cpp_invalid_template.stderr new file mode 100644 index 000000000..f6bfaaf7d --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_template.stderr @@ -0,0 +1,3 @@ +cpp_invalid_template.i:3: Error: Undefined scope 'SSS' +cpp_invalid_template.i:3: Error: Template 'SSS::AAA' undefined. +cpp_invalid_template.i:9: Error: 'JJJ' is not defined as a template. (classforward) diff --git a/Examples/test-suite/errors/cpp_namespace_template_bad.i b/Examples/test-suite/errors/cpp_namespace_template_bad.i new file mode 100644 index 000000000..5c42d6dcb --- /dev/null +++ b/Examples/test-suite/errors/cpp_namespace_template_bad.i @@ -0,0 +1,40 @@ +%module namespace_template + +namespace test { + template T max(T a, T b) { return (a > b) ? a : b; } + template class vector { + public: + vector() { } + ~vector() { } + }; +} + +namespace test2 { + using namespace test; + %template(maxshort) max; + %template(vectorshort) vector; +} + +namespace test3 { + using test::max; + using test::vector; + %template(maxlong) max; + %template(vectorlong) vector; +} + +namespace test4 { + using namespace test; + typedef int Integer; +} + +namespace test4 { + %template(maxInteger) max; + %template(vectorInteger) vector; +} + +using namespace test; +namespace test5 { + %template(maxdouble) max; + %template(vectordouble) vector; +} + diff --git a/Examples/test-suite/errors/cpp_namespace_template_bad.stderr b/Examples/test-suite/errors/cpp_namespace_template_bad.stderr new file mode 100644 index 000000000..5965d529c --- /dev/null +++ b/Examples/test-suite/errors/cpp_namespace_template_bad.stderr @@ -0,0 +1,9 @@ +cpp_namespace_template_bad.i:14: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test2' instead of within scope 'test'. +cpp_namespace_template_bad.i:15: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test2' instead of within scope 'test'. +cpp_namespace_template_bad.i:21: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test3' instead of within scope 'test'. +cpp_namespace_template_bad.i:22: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test3' instead of within scope 'test'. +cpp_namespace_template_bad.i:31: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test4' instead of within scope 'test'. +cpp_namespace_template_bad.i:32: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test4' instead of within scope 'test'. +cpp_namespace_template_bad.i:37: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test5' instead of within scope 'test'. +cpp_namespace_template_bad.i:37: Error: Template 'max' undefined. +cpp_namespace_template_bad.i:38: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test5' instead of within scope 'test'. diff --git a/Examples/test-suite/errors/cpp_namewarn.i b/Examples/test-suite/errors/cpp_namewarn.i new file mode 100644 index 000000000..c0edc4b4e --- /dev/null +++ b/Examples/test-suite/errors/cpp_namewarn.i @@ -0,0 +1,80 @@ +%module xxx + +%namewarn("314:'key1' is a keyword, renaming to '_key1'", rename="_%s") "key1"; +%namewarn("314:'key2' is a keyword, renaming to '_key2'", rename="_%s") "key2"; +%namewarn("314:'key3' is a keyword, renaming to '_key3'", rename="_%s") "key3"; +%namewarn("314:'key4' is a keyword, renaming to '_key4'", rename="_%s") "key4"; +%namewarn("314:'key5' is a keyword, renaming to '_key5'", rename="_%s") "key5"; + +// Non-templated +%ignore KlassA::key1; +%rename(key2renamed) KlassA::key2; +%rename(key3renamed) KlassA::key3; +%rename(key4renamed) KlassA::key4; + +// Templated +%ignore KlassB::key1; +%rename(key2renamed) KlassB::key2; +%rename(key3renamed) KlassB::key3; + +// Template specialized +%ignore KlassC::key1; +%rename(key2renamed) KlassC::key2; +%rename(key3renamed) KlassC::key3; + +// No warnings for these... +%inline %{ +struct KlassA { + void key1() {} + void key2() {} + void key3() {} + template void key4(X x) {} +}; + +template struct KlassB { + void key1() {} + void key2() {} + void key3() {} +}; + +template struct KlassC {}; +template<> struct KlassC { + void key1() {} + void key2() {} + void key3() {} +}; + +template void key5(T t) {} + +%} + +%template(KlassBDouble) KlassB; +%template(KlassCInt) KlassC; +%template(key5renamed) key5; + +// These should create a single warning for each keyword... +%inline %{ +struct ClassA { + void key1() {} + void key2() {} + void key3() {} + template void key4(X x) {} +}; + +template struct ClassB { + void key1() {} + void key2() {} + void key3() {} +}; + +template struct ClassC {}; +template<> struct ClassC { + void key1() {} + void key2() {} + void key3() {} +}; +%} + +%template(ClassBDouble) ClassB; +%template(ClassCInt) ClassC; +%template(key5) key5; diff --git a/Examples/test-suite/errors/cpp_namewarn.stderr b/Examples/test-suite/errors/cpp_namewarn.stderr new file mode 100644 index 000000000..e5b893268 --- /dev/null +++ b/Examples/test-suite/errors/cpp_namewarn.stderr @@ -0,0 +1,10 @@ +cpp_namewarn.i:58: Warning 314: 'key1' is a keyword, renaming to '_key1' +cpp_namewarn.i:59: Warning 314: 'key2' is a keyword, renaming to '_key2' +cpp_namewarn.i:60: Warning 314: 'key3' is a keyword, renaming to '_key3' +cpp_namewarn.i:65: Warning 314: 'key1' is a keyword, renaming to '_key1' +cpp_namewarn.i:66: Warning 314: 'key2' is a keyword, renaming to '_key2' +cpp_namewarn.i:67: Warning 314: 'key3' is a keyword, renaming to '_key3' +cpp_namewarn.i:72: Warning 314: 'key1' is a keyword, renaming to '_key1' +cpp_namewarn.i:73: Warning 314: 'key2' is a keyword, renaming to '_key2' +cpp_namewarn.i:74: Warning 314: 'key3' is a keyword, renaming to '_key3' +cpp_namewarn.i:80: Warning 314: 'key5' is a keyword, renaming to '_key5' diff --git a/Examples/test-suite/errors/cpp_nested_namespace_alias.i b/Examples/test-suite/errors/cpp_nested_namespace_alias.i new file mode 100644 index 000000000..b7cbceb71 --- /dev/null +++ b/Examples/test-suite/errors/cpp_nested_namespace_alias.i @@ -0,0 +1,34 @@ +%module cpp_nested_namespace_alias + +// C++17 nested namespaces + +namespace A +{ + namespace B + { + void ab1(); + } +} +namespace A::B +{ + void ab2(); +} +namespace AAlias = A; +namespace AAlias::B +{ + void ab3(); +} +namespace A +{ + namespace BAlias = B; + void ab4(); +} +namespace A::BAlias +{ + void ab5(); +} +namespace ABAlias = A::B; +namespace ABAlias +{ + void ab6(); +} diff --git a/Examples/test-suite/errors/cpp_nested_namespace_alias.stderr b/Examples/test-suite/errors/cpp_nested_namespace_alias.stderr new file mode 100644 index 000000000..2506a3a2c --- /dev/null +++ b/Examples/test-suite/errors/cpp_nested_namespace_alias.stderr @@ -0,0 +1,3 @@ +cpp_nested_namespace_alias.i:18: Warning 308: Namespace alias 'AAlias' not allowed here. Assuming 'A' +cpp_nested_namespace_alias.i:27: Warning 308: Namespace alias 'BAlias' not allowed here. Assuming 'B' +cpp_nested_namespace_alias.i:32: Warning 308: Namespace alias 'ABAlias' not allowed here. Assuming 'B' diff --git a/Examples/test-suite/errors/cpp_nested_template.stderr b/Examples/test-suite/errors/cpp_nested_template.stderr index 9e46cff74..363a260f6 100644 --- a/Examples/test-suite/errors/cpp_nested_template.stderr +++ b/Examples/test-suite/errors/cpp_nested_template.stderr @@ -1,2 +1,4 @@ +cpp_nested_template.i:9: Error: 'Temply' resolves to '::Temply' and was incorrectly instantiated in scope 'A' instead of within scope ''. cpp_nested_template.i:9: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template(). +cpp_nested_template.i:18: Error: 'Temply' resolves to '::Temply' and was incorrectly instantiated in scope 'B' instead of within scope ''. cpp_nested_template.i:18: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template(). diff --git a/Examples/test-suite/errors/cpp_raw_string_termination.i b/Examples/test-suite/errors/cpp_raw_string_termination.i new file mode 100644 index 000000000..3858b1f1e --- /dev/null +++ b/Examples/test-suite/errors/cpp_raw_string_termination.i @@ -0,0 +1,4 @@ +%module xxx + +%feature("docstring") func2 R"ABC(Calculate :math:`D^\nu \rho(x)`.)AB"; +void func2(double* foo, int bar, char** baz); diff --git a/Examples/test-suite/errors/cpp_raw_string_termination.stderr b/Examples/test-suite/errors/cpp_raw_string_termination.stderr new file mode 100644 index 000000000..37dd512e0 --- /dev/null +++ b/Examples/test-suite/errors/cpp_raw_string_termination.stderr @@ -0,0 +1,2 @@ +cpp_raw_string_termination.i:3: Error: Unterminated raw string, started with R"ABC( is not terminated by )ABC" +cpp_raw_string_termination.i:3: Error: Syntax error in input(1). diff --git a/Examples/test-suite/errors/cpp_refqualifier.i b/Examples/test-suite/errors/cpp_refqualifier.i new file mode 100644 index 000000000..afd6632fc --- /dev/null +++ b/Examples/test-suite/errors/cpp_refqualifier.i @@ -0,0 +1,28 @@ +%module cpp_refqualifier + +%ignore Host::h_ignored; +%ignore Host::i_ignored() &&; +%ignore Host::j_ignored() const &&; + +class Host { +public: + void h1() &; + void h2() const &; + void h3() &&; + void h4() const &&; + + void h() &; + void h() const &; + void h() &&; + void h() const &&; + + void h_ignored() &&; + void i_ignored() &&; + void i_ignored() &&; +}; + +%feature("ignore", "0") Unignore::k_unignored() const &&; + +struct Unignore { + void k_unignored() const &&; +}; diff --git a/Examples/test-suite/errors/cpp_refqualifier.stderr b/Examples/test-suite/errors/cpp_refqualifier.stderr new file mode 100644 index 000000000..ea2cd220a --- /dev/null +++ b/Examples/test-suite/errors/cpp_refqualifier.stderr @@ -0,0 +1,6 @@ +cpp_refqualifier.i:11: Warning 405: Method with rvalue ref-qualifier h3() && ignored. +cpp_refqualifier.i:12: Warning 405: Method with rvalue ref-qualifier h4() const && ignored. +cpp_refqualifier.i:16: Warning 405: Method with rvalue ref-qualifier h() && ignored. +cpp_refqualifier.i:17: Warning 405: Method with rvalue ref-qualifier h() const && ignored. +cpp_refqualifier.i:15: Warning 512: Overloaded method Host::h() const & ignored, +cpp_refqualifier.i:14: Warning 512: using non-const method Host::h() & instead. diff --git a/Examples/test-suite/errors/cpp_template_duplicate_names.i b/Examples/test-suite/errors/cpp_template_duplicate_names.i new file mode 100644 index 000000000..67f21d7bb --- /dev/null +++ b/Examples/test-suite/errors/cpp_template_duplicate_names.i @@ -0,0 +1,51 @@ +%module cpp_template_duplicate_names + +// From test-suite/template_class_reuse.i test + +%{ +namespace Space { + template struct Duplicate1 { void f(){}; }; +} +%} + +// %warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate1; +namespace Space { + template struct Duplicate1 { void f(){}; }; + template struct Duplicate1 { void f(){}; }; +} + + +// %warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate2; +%inline %{ +namespace Space { + template struct Duplicate2 { void n(){}; }; +} +%} +%template(Duplicate2_0) Space::Duplicate2<0>; +%template(Duplicate2_0) Space::Duplicate2<0>; + + +// %warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate3; +%inline %{ +namespace Space { + template struct Duplicate3 { void n(){}; }; +} +%} +%template(Duplicate3) Space::Duplicate3<0>; +%template(Duplicate3) Space::Duplicate3<0>; + + +%{ +namespace Space { + template struct Duplicate4 { void f(){}; }; +} +%} + +// %warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate4; +namespace Space { + template struct Duplicate4 { void f(){}; }; + template struct Duplicate4 { void f(){}; }; +} +%template(Duplicate4) Space::Duplicate4<0>; +%template(Duplicate4) Space::Duplicate4<0>; + diff --git a/Examples/test-suite/errors/cpp_template_duplicate_names.stderr b/Examples/test-suite/errors/cpp_template_duplicate_names.stderr new file mode 100644 index 000000000..9856ff563 --- /dev/null +++ b/Examples/test-suite/errors/cpp_template_duplicate_names.stderr @@ -0,0 +1,14 @@ +cpp_template_duplicate_names.i:14: Warning 302: Identifier 'Duplicate1' redefined (ignored), +cpp_template_duplicate_names.i:13: Warning 302: previous definition of 'Duplicate1'. +cpp_template_duplicate_names.i:14: Warning 302: Identifier 'Duplicate1' redefined (ignored), +cpp_template_duplicate_names.i:13: Warning 302: previous definition of 'Duplicate1'. +cpp_template_duplicate_names.i:25: Warning 302: Identifier 'Duplicate2_0' redefined (ignored) (Renamed from 'Duplicate2< 0 >'), +cpp_template_duplicate_names.i:24: Warning 302: previous definition of 'Duplicate2_0' (Renamed from 'Duplicate2< 0 >'). +cpp_template_duplicate_names.i:35: Warning 302: Identifier 'Duplicate3' redefined (ignored) (Renamed from 'Duplicate3< 0 >'), +cpp_template_duplicate_names.i:31: Warning 302: previous definition of 'Duplicate3'. +cpp_template_duplicate_names.i:47: Warning 302: Identifier 'Duplicate4' redefined (ignored), +cpp_template_duplicate_names.i:46: Warning 302: previous definition of 'Duplicate4'. +cpp_template_duplicate_names.i:47: Warning 302: Identifier 'Duplicate4' redefined (ignored), +cpp_template_duplicate_names.i:46: Warning 302: previous definition of 'Duplicate4'. +cpp_template_duplicate_names.i:50: Warning 302: Identifier 'Duplicate4' redefined (ignored) (Renamed from 'Duplicate4< 0 >'), +cpp_template_duplicate_names.i:46: Warning 302: previous definition of 'Duplicate4'. diff --git a/Examples/test-suite/errors/cpp_template_scope.i b/Examples/test-suite/errors/cpp_template_scope.i new file mode 100644 index 000000000..ec0f0a577 --- /dev/null +++ b/Examples/test-suite/errors/cpp_template_scope.i @@ -0,0 +1,57 @@ +%module xxx + +namespace std { + template class vector {}; +} + +struct S1 {}; +struct S2 {}; +struct S3 {}; +struct S4 {}; +struct S5 {}; +struct S6 {}; +struct S7 {}; + +// valid +namespace std { + %template(vi1) vector; + template class vector; +} + +// valid +using namespace std; +%template(vi2) vector; +template class vector; + +// valid +using std::vector; +%template(vi3) vector; +template class vector; + +// ill-formed +namespace unrelated { + using std::vector; + %template(vi4) vector; + template class vector; +} + +// ill-formed +namespace unrelated { + using namespace std; + %template(vi5) vector; + template class vector; +} + +// ill-formed +namespace unrelated { + namespace std { + %template(vi6) vector; + template class vector; + } +} + +// ill-formed +namespace unrelated { + %template(vi7) std::vector; + template class std::vector; +} diff --git a/Examples/test-suite/errors/cpp_template_scope.stderr b/Examples/test-suite/errors/cpp_template_scope.stderr new file mode 100644 index 000000000..e47630268 --- /dev/null +++ b/Examples/test-suite/errors/cpp_template_scope.stderr @@ -0,0 +1,11 @@ +cpp_template_scope.i:18: Warning 320: Explicit template instantiation ignored. +cpp_template_scope.i:24: Warning 320: Explicit template instantiation ignored. +cpp_template_scope.i:29: Warning 320: Explicit template instantiation ignored. +cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'. +cpp_template_scope.i:35: Warning 320: Explicit template instantiation ignored. +cpp_template_scope.i:41: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'. +cpp_template_scope.i:42: Warning 320: Explicit template instantiation ignored. +cpp_template_scope.i:48: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated::std' instead of within scope 'std'. +cpp_template_scope.i:49: Warning 320: Explicit template instantiation ignored. +cpp_template_scope.i:55: Error: 'std::vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'. +cpp_template_scope.i:56: Warning 320: Explicit template instantiation ignored. diff --git a/Examples/test-suite/errors/cpp_using_type_aliasing.i b/Examples/test-suite/errors/cpp_using_type_aliasing.i deleted file mode 100644 index df65dbd3d..000000000 --- a/Examples/test-suite/errors/cpp_using_type_aliasing.i +++ /dev/null @@ -1,13 +0,0 @@ -%module cpp_using_type_aliasing - -namespace Space { - template struct Okay { - }; - struct User { - protected: - using OkayInt = Okay; - }; - struct Derived : User { - Okay ff(); - }; -}; diff --git a/Examples/test-suite/errors/cpp_using_type_aliasing.stderr b/Examples/test-suite/errors/cpp_using_type_aliasing.stderr deleted file mode 100644 index e69de29bb..000000000 diff --git a/Examples/test-suite/errors/doxygen_unknown_command.i b/Examples/test-suite/errors/doxygen_unknown_command.i new file mode 100644 index 000000000..0f32ee966 --- /dev/null +++ b/Examples/test-suite/errors/doxygen_unknown_command.i @@ -0,0 +1,6 @@ +%module xxx + +/** + There is an \unknown Doxygen comment here. + */ +void foo(); diff --git a/Examples/test-suite/errors/doxygen_unknown_command.stderr b/Examples/test-suite/errors/doxygen_unknown_command.stderr new file mode 100644 index 000000000..e5c32cc4b --- /dev/null +++ b/Examples/test-suite/errors/doxygen_unknown_command.stderr @@ -0,0 +1 @@ +doxygen_unknown_command.i:4: Warning 560: Unknown Doxygen command: unknown. diff --git a/Examples/test-suite/errors/pp_expressions_bad.i b/Examples/test-suite/errors/pp_expressions_bad.i new file mode 100644 index 000000000..454437f95 --- /dev/null +++ b/Examples/test-suite/errors/pp_expressions_bad.i @@ -0,0 +1,43 @@ +%module xxx +/* Note: needs -Wextra to see these warnings */ + +/* Divide by zero */ +#define ZERO 0 + +#if 1%ZERO +#endif +#if 2/ZERO +#endif + +#if 1%(5-5) +#endif +#if 2/(55-55) +#endif + +/* Floating point */ +#if 1.2 +#endif + +#if 2e3 +#endif + +#if 0 +#elif 8.8 +#endif + +/* Missing whitespace after preproc directive */ +#if123 +#endif + +#if456e +#endif + +#if 0 +#warning This should not warn +#elif1 +#warning This should also not warn +#endif + +#if(1) +#warning Warning okay: #if(1) +#endif diff --git a/Examples/test-suite/errors/pp_expressions_bad.stderr b/Examples/test-suite/errors/pp_expressions_bad.stderr new file mode 100644 index 000000000..84104c6a8 --- /dev/null +++ b/Examples/test-suite/errors/pp_expressions_bad.stderr @@ -0,0 +1,19 @@ +pp_expressions_bad.i:7: Warning 202: Could not evaluate expression '1%ZERO' +pp_expressions_bad.i:7: Warning 202: Error: 'Modulo by zero in expression' +pp_expressions_bad.i:9: Warning 202: Could not evaluate expression '2/ZERO' +pp_expressions_bad.i:9: Warning 202: Error: 'Division by zero in expression' +pp_expressions_bad.i:12: Warning 202: Could not evaluate expression '1%(5-5)' +pp_expressions_bad.i:12: Warning 202: Error: 'Modulo by zero in expression' +pp_expressions_bad.i:14: Warning 202: Could not evaluate expression '2/(55-55)' +pp_expressions_bad.i:14: Warning 202: Error: 'Division by zero in expression' +pp_expressions_bad.i:18: Warning 202: Could not evaluate expression '1.2' +pp_expressions_bad.i:18: Warning 202: Error: 'Floating point constant in preprocessor expression' +pp_expressions_bad.i:21: Warning 202: Could not evaluate expression '2e3' +pp_expressions_bad.i:21: Warning 202: Error: 'Floating point constant in preprocessor expression' +pp_expressions_bad.i:25: Warning 202: Could not evaluate expression '8.8' +pp_expressions_bad.i:25: Warning 202: Error: 'Floating point constant in preprocessor expression' +pp_expressions_bad.i:29: Error: Unknown SWIG preprocessor directive: if123 (if this is a block of target language code, delimit it with %{ and %}) +pp_expressions_bad.i:30: Error: Extraneous #endif. +pp_expressions_bad.i:32: Error: Unknown SWIG preprocessor directive: if456e (if this is a block of target language code, delimit it with %{ and %}) +pp_expressions_bad.i:33: Error: Extraneous #endif. +pp_expressions_bad.i:42: Warning 204: CPP #warning, "Warning okay: #if(1)". diff --git a/Examples/test-suite/errors/pp_invalid_exponents.i b/Examples/test-suite/errors/pp_invalid_exponents.i new file mode 100644 index 000000000..73dcdb145 --- /dev/null +++ b/Examples/test-suite/errors/pp_invalid_exponents.i @@ -0,0 +1,7 @@ +%module xxx + +#if 123e +#endif + +#if 456.e +#endif diff --git a/Examples/test-suite/errors/pp_invalid_exponents.stderr b/Examples/test-suite/errors/pp_invalid_exponents.stderr new file mode 100644 index 000000000..735a31ceb --- /dev/null +++ b/Examples/test-suite/errors/pp_invalid_exponents.stderr @@ -0,0 +1,6 @@ +:EOF: Error: Exponent does not have any digits +pp_invalid_exponents.i:3: Warning 202: Could not evaluate expression '123e' +pp_invalid_exponents.i:3: Warning 202: Error: 'Syntax error' +:EOF: Error: Exponent does not have any digits +pp_invalid_exponents.i:6: Warning 202: Could not evaluate expression '456.e' +pp_invalid_exponents.i:6: Warning 202: Error: 'Syntax error' diff --git a/Examples/test-suite/errors/pp_macro_missing_expression.i b/Examples/test-suite/errors/pp_macro_missing_expression.i index 2c7c9855d..a93a76f2e 100644 --- a/Examples/test-suite/errors/pp_macro_missing_expression.i +++ b/Examples/test-suite/errors/pp_macro_missing_expression.i @@ -1,4 +1,4 @@ -// Test "Missing identifier for ..." errrors +// Test "Missing identifier for ..." errors %module xxx #ifdef diff --git a/Examples/test-suite/errors/pp_unknowndirective3.i b/Examples/test-suite/errors/pp_unknowndirective3.i new file mode 100644 index 000000000..77dfd5bb5 --- /dev/null +++ b/Examples/test-suite/errors/pp_unknowndirective3.i @@ -0,0 +1,14 @@ +%module xxx + +// Testing is_digits detecting gcc linemarkers + +// These are valid +# 1 "/usr/include/stdc-predef.h" 1 3 4 +# 123 "header1.h" + +// These are invalid +#a1 'a.h' +#1b 'b.h' +#1c1 'c.h' +#d1d 'd.h' + diff --git a/Examples/test-suite/errors/pp_unknowndirective3.stderr b/Examples/test-suite/errors/pp_unknowndirective3.stderr new file mode 100644 index 000000000..35bff8a80 --- /dev/null +++ b/Examples/test-suite/errors/pp_unknowndirective3.stderr @@ -0,0 +1,4 @@ +pp_unknowndirective3.i:10: Error: Unknown SWIG preprocessor directive: a1 (if this is a block of target language code, delimit it with %{ and %}) +pp_unknowndirective3.i:11: Error: Unknown SWIG preprocessor directive: 1b (if this is a block of target language code, delimit it with %{ and %}) +pp_unknowndirective3.i:12: Error: Unknown SWIG preprocessor directive: 1c1 (if this is a block of target language code, delimit it with %{ and %}) +pp_unknowndirective3.i:13: Error: Unknown SWIG preprocessor directive: d1d (if this is a block of target language code, delimit it with %{ and %}) diff --git a/Examples/test-suite/exception_classname.i b/Examples/test-suite/exception_classname.i index 6900581cf..ed8c433eb 100644 --- a/Examples/test-suite/exception_classname.i +++ b/Examples/test-suite/exception_classname.i @@ -1,7 +1,7 @@ %module exception_classname %warnfilter(SWIGWARN_RUBY_WRONG_NAME); -#ifdef SWIGPHP +#if defined(SWIGPHP) || defined(SWIGD) %rename(ExceptionClass) Exception; #endif diff --git a/Examples/test-suite/exception_order.i b/Examples/test-suite/exception_order.i index bca745c7e..e2411634b 100644 --- a/Examples/test-suite/exception_order.i +++ b/Examples/test-suite/exception_order.i @@ -12,10 +12,10 @@ %include "exception.i" +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) %{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +#define TESTCASE_THROW1(T1) %} /* @@ -23,7 +23,17 @@ user's throw declarations. */ -#if defined(SWIGUTL) +#if defined(SWIGOCTAVE) +%exception { + try { + $action + } + SWIG_RETHROW_OCTAVE_EXCEPTIONS + catch(...) { + SWIG_exception(SWIG_RuntimeError,"postcatch unknown"); + } +} +#elif defined(SWIGUTL) %exception { try { $action @@ -89,16 +99,16 @@ int efoovar; /* caught by the user's throw definition */ - int foo() throw(E1) + int foo() TESTCASE_THROW1(E1) { throw E1(); - return 0; + return 0; } - - int bar() throw(E2) + + int bar() TESTCASE_THROW1(E2) { throw E2(); - return 0; + return 0; } /* caught by %postexception */ @@ -136,3 +146,4 @@ bool is_python_builtin() { return false; } %template(ET_i) ET; %template(ET_d) ET; + diff --git a/Examples/test-suite/exception_partial_info.i b/Examples/test-suite/exception_partial_info.i index 47b046735..3ac465cf6 100644 --- a/Examples/test-suite/exception_partial_info.i +++ b/Examples/test-suite/exception_partial_info.i @@ -2,10 +2,10 @@ // This produced compilable code for Tcl, Python in 1.3.27, fails in 1.3.29 +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) %{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +#define TESTCASE_THROW1(T1) %} %{ @@ -36,8 +36,8 @@ class ex2 : public myException class Impl { public: - void f1() throw (myException) { ex1 e; throw e; } - void f2() throw (myException) { ex2 e; throw e; } + void f1() TESTCASE_THROW1(myException) { ex1 e; throw e; } + void f2() TESTCASE_THROW1(myException) { ex2 e; throw e; } }; %} diff --git a/Examples/test-suite/extend.i b/Examples/test-suite/extend.i index 29e258f5b..ab0c651a5 100644 --- a/Examples/test-suite/extend.i +++ b/Examples/test-suite/extend.i @@ -1,5 +1,9 @@ %module extend +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %extend Base { ~Base() { delete $self; diff --git a/Examples/test-suite/extend_template_method.i b/Examples/test-suite/extend_template_method.i new file mode 100644 index 000000000..8c03d9b51 --- /dev/null +++ b/Examples/test-suite/extend_template_method.i @@ -0,0 +1,92 @@ +%module extend_template_method + +%include + +%inline %{ +namespace Space { +class ExtendMe { +public: + ExtendMe() {} + template + T do_stuff_impl(int a, T b, double d) { + return b; + } +}; +} +%} + +%extend Space::ExtendMe { + template + T do_stuff(int a, T b) { + return $self->do_stuff_impl(a, b, 4.0); + } + template + T do_overloaded_stuff(T b) { + return $self->do_stuff_impl(0, b, 4.0); + } + template + static T static_method(T t) { + return t; + } + template + ExtendMe(T x) { + Space::ExtendMe *em = new Space::ExtendMe(); + return em; + } +} +%template(do_stuff_double) Space::ExtendMe::do_stuff; +%template(do_stuff_string) Space::ExtendMe::do_stuff; + +%template(do_overloaded_stuff) Space::ExtendMe::do_overloaded_stuff; +%template(do_overloaded_stuff) Space::ExtendMe::do_overloaded_stuff; + +%template(static_method) Space::ExtendMe::static_method; + +%template(ExtendMe) Space::ExtendMe::ExtendMe; + +%inline %{ +namespace Space { +template +class TemplateExtendMe { +public: + TemplateExtendMe() {} + template + T template_stuff_impl(X a, T b, double d) { + return b; + } +}; +} +%} + +%extend Space::TemplateExtendMe { + template + T do_template_stuff(int a, T b) { + return $self->template_stuff_impl(a, b, 4.0); + } + template + T do_template_overloaded_stuff(T b) { + return $self->template_stuff_impl(0, b, 4.0); + } + template + static T static_template_method(T t) { + return t; + } + template + TemplateExtendMe(T x) { + Space::TemplateExtendMe *em = new Space::TemplateExtendMe(); + return em; + } + +%template(do_template_stuff_double) do_template_stuff; +%template(do_template_stuff_string) do_template_stuff; + +%template(do_template_overloaded_stuff) do_template_overloaded_stuff; +%template(do_template_overloaded_stuff) do_template_overloaded_stuff; + +%template(static_template_method) static_template_method; + +%template(TemplateExtendMe) Space::TemplateExtendMe::TemplateExtendMe; +} + +%template(TemplateExtend) Space::TemplateExtendMe; + diff --git a/Examples/test-suite/extern_throws.i b/Examples/test-suite/extern_throws.i index eab26244e..92ece4158 100644 --- a/Examples/test-suite/extern_throws.i +++ b/Examples/test-suite/extern_throws.i @@ -1,18 +1,18 @@ %module extern_throws +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) %{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +#define TESTCASE_THROW1(T1) %} %inline %{ #include -extern int get() throw(std::exception); +extern int get() TESTCASE_THROW1(std::exception); %} %{ -int get() throw(std::exception) { return 0; } +int get() TESTCASE_THROW1(std::exception) { return 0; } %} diff --git a/Examples/test-suite/features.i b/Examples/test-suite/features.i index 2ccbe725a..a8b56527d 100644 --- a/Examples/test-suite/features.i +++ b/Examples/test-suite/features.i @@ -2,6 +2,10 @@ %warnfilter(SWIGWARN_LANG_IDENTIFIER,SWIGWARN_IGNORE_OPERATOR_PLUSEQ); +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + // This testcase checks that %feature is working for templates and non user supplied constructors/destructors and is just generally working // If the default %exception is used it will not compile. It shouldn't get used. diff --git a/Examples/test-suite/friends.i b/Examples/test-suite/friends.i index 2dfee6f3b..1ba1e5e17 100644 --- a/Examples/test-suite/friends.i +++ b/Examples/test-suite/friends.i @@ -5,7 +5,12 @@ %warnfilter(SWIGWARN_LANG_IDENTIFIER); - +#if defined(SWIGOCTAVE) +%warnfilter(SWIGWARN_IGNORE_OPERATOR_LSHIFT_MSG) operator<<; +%warnfilter(SWIGWARN_IGNORE_OPERATOR_RSHIFT_MSG) operator>>; +#endif + + %inline { diff --git a/Examples/test-suite/friends_template.i b/Examples/test-suite/friends_template.i index 48623f2ca..363e88f16 100644 --- a/Examples/test-suite/friends_template.i +++ b/Examples/test-suite/friends_template.i @@ -1,5 +1,10 @@ %module friends_template +#if defined(SWIGOCTAVE) +%warnfilter(SWIGWARN_IGNORE_OPERATOR_RSHIFT_MSG) operator>>; +#endif + + %{ template class MyClass; diff --git a/Examples/test-suite/funcptr_cpp.i b/Examples/test-suite/funcptr_cpp.i index b63749dc1..d8ec8de4d 100644 --- a/Examples/test-suite/funcptr_cpp.i +++ b/Examples/test-suite/funcptr_cpp.i @@ -15,6 +15,9 @@ int & addByReference(const int &a, int b) { static int val; val = a+b; return va int call1(int (*d)(const int &, int), int a, int b) { return d(a, b); } int call2(int * (*d)(const int &, int), int a, int b) { return *d(a, b); } int call3(int & (*d)(const int &, int), int a, int b) { return d(a, b); } +int call4(int & (*d)(int &, int *), int a, int b) { return d(a, &b); } +int call5(int & (*d)(int &, int const * const), int a, int b) { return d(a, &b); } +int callconst1(int (* const d)(const int &, int), int a, int b) { return d(a, b); } %} %constant int (*ADD_BY_VALUE)(const int &, int) = addByValue; diff --git a/Examples/test-suite/functors.i b/Examples/test-suite/functors.i new file mode 100644 index 000000000..363123000 --- /dev/null +++ b/Examples/test-suite/functors.i @@ -0,0 +1,33 @@ +%module functors + +// Rename operator() only if the language does not already do this by default +#if defined(SWIGCSHARP) || defined(SWIGGO) || defined(SWIGGUILE) || defined(SWIGJAVA) || defined(SWIGJAVASCRIPT) || defined(SWIGPHP) || defined(SWIGSCILAB) || defined(SWIGTCL) +%rename(Funktor) operator(); +#endif + +%inline %{ +class Functor0 { + int num; +public: + Functor0(int num) : num(num) {} + int operator()() { return -num; } + int operate() { return this->operator()(); } +}; + +class Functor1 { + int num; +public: + Functor1(int num) : num(num) {} + int operator()(int x) { return num + x; } + int operate(int x) { return this->operator()(x); } +}; + +class Functor2 { + int num; +public: + Functor2(int num) : num(num) {} + int operator()(int x, int x2) { return num + x + x2; } + int operate(int x, int x2) { return this->operator()(x, x2); } +}; +%} + diff --git a/Examples/test-suite/go/Makefile.in b/Examples/test-suite/go/Makefile.in index 01989b0d3..d07a56bec 100644 --- a/Examples/test-suite/go/Makefile.in +++ b/Examples/test-suite/go/Makefile.in @@ -73,7 +73,18 @@ INCLUDES = -I$(abs_top_srcdir)/$(EXAMPLES)/$(TEST_SUITE) %.multicpptest: $(setup) - +$(swig_and_compile_multi_cpp) + mkdir -p gopath/$*/src 2>/dev/null || true + if ! test -d gopath/$*/src/swigtests; then \ + (cd gopath/$*/src && ln -s . swigtests); \ + fi + +for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + LIBS='$(LIBS)' INCLUDES='$(INCLUDES)' SWIGOPT='$(SWIGOPT)' NOLINK=true \ + TARGET="$(TARGETPREFIX)$${f}$(TARGETSUFFIX)" INTERFACEDIR='$(INTERFACEDIR)' INTERFACE="$$f.i" \ + GOMOD="$*" \ + $(LANGUAGE)$(VARIANT)_cpp; \ + done $(run_multi_testcase) li_windows.cpptest: @@ -82,50 +93,55 @@ li_windows.cpptest: multi_import.multicpptest: $(setup) + mkdir -p gopath/multi_import/src 2>/dev/null || true + if ! test -d gopath/multi_import/src/swigtests; then \ + (cd gopath/multi_import/src && ln -s . swigtests); \ + fi for f in multi_import_b multi_import_a; do \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ LIBS='$(LIBS)' INCLUDES='$(INCLUDES)' SWIGOPT='$(SWIGOPT)' NOLINK=true \ TARGET="$(TARGETPREFIX)$${f}$(TARGETSUFFIX)" INTERFACEDIR='$(INTERFACEDIR)' INTERFACE="$$f.i" \ + GOMOD="multi_import" \ $(LANGUAGE)$(VARIANT)_cpp; \ done $(run_multi_testcase) go_subdir_import.multicpptest: $(setup) - mkdir -p testdir/go_subdir_import/ - mkdir -p gopath/src/testdir/go_subdir_import/ + mkdir -p gopath/go_subdir_import/src 2>/dev/null || true + if ! test -d gopath/go_subdir_import/src/swigtests; then \ + (cd gopath/go_subdir_import/src && ln -s . swigtests); \ + fi + mkdir -p testdir/go_subdir_import 2>/dev/null || true + mkdir -p gopath/go_subdir_import/src/testdir/go_subdir_import 2>/dev/null || true $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ LIBS='$(LIBS)' INTERFACEPATH='$(SRCDIR)$(INTERFACEDIR)go_subdir_import_b.i' \ INCLUDES='$(INCLUDES)' SWIGOPT='$(SWIGOPT) -outdir .' NOLINK=true \ TARGET='$(TARGETPREFIX)go_subdir_import_b$(TARGETSUFFIX)' INTERFACEDIR='$(INTERFACEDIR)' \ INTERFACE='testdir/go_subdir_import/go_subdir_import_b.i' \ + GOMOD="go_subdir_import" \ $(LANGUAGE)$(VARIANT)_cpp; for f in testdir/go_subdir_import/go_subdir_import_c go_subdir_import_a ; do \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ LIBS='$(LIBS)' INCLUDES='$(INCLUDES)' SWIGOPT='$(SWIGOPT)' NOLINK=true \ TARGET="$(TARGETPREFIX)$${f}$(TARGETSUFFIX)" INTERFACEDIR='$(INTERFACEDIR)' INTERFACE="$$f.i" \ + GOMOD="go_subdir_import" \ $(LANGUAGE)$(VARIANT)_cpp; \ done - if $(GOGCC); then \ - cp gopath/src/testdir/go_subdir_import/go_subdir_import_b/go_subdir_import_b.a gopath/src/testdir/go_subdir_import/go_subdir_import_b.gox; \ - cp gopath/src/testdir/go_subdir_import/go_subdir_import_b/go_subdir_import_b.a .; \ - cp gopath/src/testdir/go_subdir_import/go_subdir_import_c/go_subdir_import_c.a gopath/src/testdir/go_subdir_import/go_subdir_import_c.gox; \ - cp gopath/src/testdir/go_subdir_import/go_subdir_import_c/go_subdir_import_c.a testdir/go_subdir_import/; \ - fi $(run_multi_testcase) # Runs the testcase. run_testcase = \ if test -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); then \ if $(GOGCC) ; then \ - $(COMPILETOOL) $(GCCGO) -c -g -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ - $(COMPILETOOL) $(GCCGO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ $*.a; \ + $(COMPILETOOL) $(GCCGO) -c -g -I gopath/src/$* $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ + $(COMPILETOOL) $(GCCGO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ gopath/src/$*/$*.a; \ elif $(GO12) || $(GO13) || $(GO15); then \ - $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ - $(COMPILETOOL) $(GOTOOL) $(GOLD) -linkmode external -extld $(CC) -extldflags "$(CFLAGS) $(OSXOLDGOLINKFLAGS)" -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \ + $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I gopath/src/$* $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ + $(COMPILETOOL) $(GOTOOL) $(GOLD) -L gopath/src/$* -linkmode external -extld $(CC) -extldflags "$(CFLAGS) $(OSXOLDGOLINKFLAGS)" -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \ else \ $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ $(COMPILETOOL) $(GOTOOL) $(GOLD) -L . -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \ @@ -136,11 +152,11 @@ run_testcase = \ run_testcase_cpp = \ if test -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); then \ if $(GOGCC) ; then \ - $(COMPILETOOL) $(GCCGO) -c -g -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ - $(COMPILETOOL) $(GCCGO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ $*.a -lstdc++; \ + $(COMPILETOOL) $(GCCGO) -c -g -I gopath/src/$* $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ + $(COMPILETOOL) $(GCCGO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ gopath/src/$*/$*.a -lstdc++; \ elif $(GO12) || $(GO13) || $(GO15); then \ - $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ - $(COMPILETOOL) $(GOTOOL) $(GOLD) -linkmode external -extld $(CXX) -extldflags "$(CXXFLAGS) $(OSXOLDGOLINKFLAGS)" -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \ + $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I gopath/src/$* $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ + $(COMPILETOOL) $(GOTOOL) $(GOLD) -L gopath/src/$* -linkmode external -extld $(CXX) -extldflags "$(CXXFLAGS) $(OSXOLDGOLINKFLAGS)" -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \ else \ $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ $(COMPILETOOL) $(GOTOOL) $(GOLD) -L . -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \ @@ -150,18 +166,24 @@ run_testcase_cpp = \ run_multi_testcase = \ if test -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); then \ - if $(GOGCC) ; then \ - $(COMPILETOOL) $(GCCGO) -c -g -I . -I gopath/src $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ + if $(GO15) || $(GOGCC); then \ files=`cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list`; \ - $(COMPILETOOL) $(GCCGO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ `for f in $$files; do echo $$f.a; done` -lstdc++; \ - elif $(GO12) || $(GO13) || $(GO15); then \ - $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ - $(COMPILETOOL) $(GOTOOL) $(GOLD) -L . -linkmode external -extld $(CXX) -extldflags "$(CXXFLAGS) $(OSXOLDGOLINKFLAGS)" -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \ - else \ - $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ - $(COMPILETOOL) $(GOTOOL) $(GOLD) -L . -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \ - fi && \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) ./$*_runme; \ + mkdir gopath/$*/src/$* 2>/dev/null || true; \ + cp $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) gopath/$*/src/$*; \ + GOPATH="`pwd`/gopath/$*"; \ + export GOPATH; \ + CGO_CPPFLAGS="$(CPPFLAGS) $(INCLUDES) `for f in $$files; do echo -I ../$$f; done`"; \ + export CGO_CPPFLAGS; \ + CGO_CFLAGS="$(CFLAGS)"; \ + export CGO_CFLAGS; \ + CGO_CXXFLAGS="$(CXXFLAGS)"; \ + export CGO_CXXFLAGS; \ + CGO_LDFLAGS="$(LDFLAGS) -lm"; \ + export CGO_LDFLAGS; \ + (cd gopath/$*/src/$* && \ + $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o ../../../../$*_runme) && \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) ./$*_runme; \ + fi; \ fi %.clean: @@ -182,12 +204,3 @@ clean: rm -f import_stl_a.go import_stl_a.gox rm -f import_stl_b.go import_stl_b.gox rm -rf gopath - -cvsignore: - @echo '*_gc.c *_wrap.* *.so *.dll *.exp *.lib' - @echo Makefile - @echo mod_a.go mod_b.go imports_a.go imports_b.go - @echo clientdata_prop_a.go clientdata_prop_b.go - @echo multi_import_a.go multi_import_b.go - @echo packageoption_a.go packageoption_b.go packageoption_c.go - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.go; done diff --git a/Examples/test-suite/go/abstract_access_runme.go b/Examples/test-suite/go/abstract_access_runme.go index a2cfeda92..5102236f9 100644 --- a/Examples/test-suite/go/abstract_access_runme.go +++ b/Examples/test-suite/go/abstract_access_runme.go @@ -1,6 +1,6 @@ package main -import "./abstract_access" +import "abstract_access" func main() { d := abstract_access.NewD() diff --git a/Examples/test-suite/go/abstract_typedef2_runme.go b/Examples/test-suite/go/abstract_typedef2_runme.go index ef760e45d..76a5fc8de 100644 --- a/Examples/test-suite/go/abstract_typedef2_runme.go +++ b/Examples/test-suite/go/abstract_typedef2_runme.go @@ -1,6 +1,6 @@ package main -import "./abstract_typedef2" +import "abstract_typedef2" func main() { abstract_typedef2.NewA_UF() diff --git a/Examples/test-suite/go/abstract_typedef_runme.go b/Examples/test-suite/go/abstract_typedef_runme.go index 99ff94ded..56aaa613f 100644 --- a/Examples/test-suite/go/abstract_typedef_runme.go +++ b/Examples/test-suite/go/abstract_typedef_runme.go @@ -1,6 +1,6 @@ package main -import "./abstract_typedef" +import "abstract_typedef" func main() { e := abstract_typedef.NewEngine() diff --git a/Examples/test-suite/go/abstract_virtual_runme.go b/Examples/test-suite/go/abstract_virtual_runme.go index b87cf9b5c..e19eac27d 100644 --- a/Examples/test-suite/go/abstract_virtual_runme.go +++ b/Examples/test-suite/go/abstract_virtual_runme.go @@ -1,6 +1,6 @@ package main -import "./abstract_virtual" +import "abstract_virtual" func main() { abstract_virtual.NewD() diff --git a/Examples/test-suite/go/argout_runme.go b/Examples/test-suite/go/argout_runme.go index 5f7017e73..bb8ab9ed2 100644 --- a/Examples/test-suite/go/argout_runme.go +++ b/Examples/test-suite/go/argout_runme.go @@ -1,6 +1,6 @@ package main -import wrap "./argout" +import wrap "argout" func main() { ip := wrap.New_intp() diff --git a/Examples/test-suite/go/array_member_runme.go b/Examples/test-suite/go/array_member_runme.go index d8a8fac2b..4f029db98 100644 --- a/Examples/test-suite/go/array_member_runme.go +++ b/Examples/test-suite/go/array_member_runme.go @@ -1,6 +1,6 @@ package main -import . "./array_member" +import . "array_member" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/arrays_global_runme.go b/Examples/test-suite/go/arrays_global_runme.go index 0ff40090c..35b049d9a 100644 --- a/Examples/test-suite/go/arrays_global_runme.go +++ b/Examples/test-suite/go/arrays_global_runme.go @@ -1,6 +1,6 @@ package main -import . "./arrays_global" +import . "arrays_global" func main() { SetArray_i(GetArray_const_i()) diff --git a/Examples/test-suite/go/char_binary_runme.go b/Examples/test-suite/go/char_binary_runme.go index 50f2e121d..d47d616af 100644 --- a/Examples/test-suite/go/char_binary_runme.go +++ b/Examples/test-suite/go/char_binary_runme.go @@ -1,6 +1,6 @@ package main -import . "./char_binary" +import . "char_binary" func main() { t := NewTest() diff --git a/Examples/test-suite/go/class_ignore_runme.go b/Examples/test-suite/go/class_ignore_runme.go index 82e52eff5..24261c637 100644 --- a/Examples/test-suite/go/class_ignore_runme.go +++ b/Examples/test-suite/go/class_ignore_runme.go @@ -1,6 +1,6 @@ package main -import "./class_ignore" +import "class_ignore" func main() { a := class_ignore.NewBar() diff --git a/Examples/test-suite/go/class_scope_weird_runme.go b/Examples/test-suite/go/class_scope_weird_runme.go index 332586f31..a42bdad21 100644 --- a/Examples/test-suite/go/class_scope_weird_runme.go +++ b/Examples/test-suite/go/class_scope_weird_runme.go @@ -1,6 +1,6 @@ package main -import "./class_scope_weird" +import "class_scope_weird" func main() { f := class_scope_weird.NewFoo() diff --git a/Examples/test-suite/go/compactdefaultargs_runme.go b/Examples/test-suite/go/compactdefaultargs_runme.go index 46f3ff3f9..fe6224ca2 100644 --- a/Examples/test-suite/go/compactdefaultargs_runme.go +++ b/Examples/test-suite/go/compactdefaultargs_runme.go @@ -1,6 +1,6 @@ package main -import . "./compactdefaultargs" +import . "compactdefaultargs" func main() { defaults1 := NewDefaults1(1000) diff --git a/Examples/test-suite/go/constover_runme.go b/Examples/test-suite/go/constover_runme.go index f961e01b5..6c837095a 100644 --- a/Examples/test-suite/go/constover_runme.go +++ b/Examples/test-suite/go/constover_runme.go @@ -1,9 +1,10 @@ package main import ( - "./constover" "fmt" "os" + + "constover" ) func main() { diff --git a/Examples/test-suite/go/constructor_copy_runme.go b/Examples/test-suite/go/constructor_copy_runme.go index d9b77a9db..68c428853 100644 --- a/Examples/test-suite/go/constructor_copy_runme.go +++ b/Examples/test-suite/go/constructor_copy_runme.go @@ -1,6 +1,6 @@ package main -import . "./constructor_copy" +import . "constructor_copy" func main() { f1 := NewFoo1(3) diff --git a/Examples/test-suite/go/contract_runme.go b/Examples/test-suite/go/contract_runme.go index b20a1a64f..b028855c3 100644 --- a/Examples/test-suite/go/contract_runme.go +++ b/Examples/test-suite/go/contract_runme.go @@ -1,6 +1,6 @@ package main -import "./contract" +import "contract" func main() { contract.Test_preassert(1, 2) diff --git a/Examples/test-suite/go/cpp11_strongly_typed_enumerations_runme.go b/Examples/test-suite/go/cpp11_strongly_typed_enumerations_runme.go index f4b84b1ee..f9ca74a1e 100644 --- a/Examples/test-suite/go/cpp11_strongly_typed_enumerations_runme.go +++ b/Examples/test-suite/go/cpp11_strongly_typed_enumerations_runme.go @@ -1,7 +1,7 @@ package main import "fmt" -import . "./cpp11_strongly_typed_enumerations" +import . "cpp11_strongly_typed_enumerations" func enumCheck(actual int, expected int) int { if actual != expected { diff --git a/Examples/test-suite/go/cpp_enum_runme.go b/Examples/test-suite/go/cpp_enum_runme.go index 7d7db953d..8906dd4f1 100644 --- a/Examples/test-suite/go/cpp_enum_runme.go +++ b/Examples/test-suite/go/cpp_enum_runme.go @@ -1,6 +1,6 @@ package main -import "./cpp_enum" +import "cpp_enum" func main() { f := cpp_enum.NewFoo() diff --git a/Examples/test-suite/go/cpp_namespace_runme.go b/Examples/test-suite/go/cpp_namespace_runme.go index 8482b043f..aecdd9543 100644 --- a/Examples/test-suite/go/cpp_namespace_runme.go +++ b/Examples/test-suite/go/cpp_namespace_runme.go @@ -1,7 +1,7 @@ // Note: This example assumes that namespaces are flattened package main -import "./cpp_namespace" +import "cpp_namespace" func main() { n := cpp_namespace.Fact(4) diff --git a/Examples/test-suite/go/cpp_static_runme.go b/Examples/test-suite/go/cpp_static_runme.go index ead433466..1ad981a60 100644 --- a/Examples/test-suite/go/cpp_static_runme.go +++ b/Examples/test-suite/go/cpp_static_runme.go @@ -1,6 +1,6 @@ package main -import . "./cpp_static" +import . "cpp_static" func main() { StaticFunctionTestStatic_func() diff --git a/Examples/test-suite/go/default_args_runme.go b/Examples/test-suite/go/default_args_runme.go index 38243ac44..a39f95716 100644 --- a/Examples/test-suite/go/default_args_runme.go +++ b/Examples/test-suite/go/default_args_runme.go @@ -1,6 +1,6 @@ package main -import "./default_args" +import "default_args" func main() { if default_args.StaticsStaticmethod() != 60 { diff --git a/Examples/test-suite/go/default_constructor_runme.go b/Examples/test-suite/go/default_constructor_runme.go index 40a5a6e49..eeac7eaf8 100644 --- a/Examples/test-suite/go/default_constructor_runme.go +++ b/Examples/test-suite/go/default_constructor_runme.go @@ -1,6 +1,6 @@ package main -import dc "./default_constructor" +import dc "default_constructor" func main() { a := dc.NewA() diff --git a/Examples/test-suite/go/director_alternating_runme.go b/Examples/test-suite/go/director_alternating_runme.go index 10f6774a3..b4793aa8f 100644 --- a/Examples/test-suite/go/director_alternating_runme.go +++ b/Examples/test-suite/go/director_alternating_runme.go @@ -1,6 +1,6 @@ package main -import . "./director_alternating" +import . "director_alternating" func main() { id := GetBar().Id() diff --git a/Examples/test-suite/go/director_basic_runme.go b/Examples/test-suite/go/director_basic_runme.go index 0ce780bbd..360424d9b 100644 --- a/Examples/test-suite/go/director_basic_runme.go +++ b/Examples/test-suite/go/director_basic_runme.go @@ -1,6 +1,6 @@ package main -import "./director_basic" +import "director_basic" type GoFoo struct{} diff --git a/Examples/test-suite/go/director_classic_runme.go b/Examples/test-suite/go/director_classic_runme.go index 45e89eac5..230c9638d 100644 --- a/Examples/test-suite/go/director_classic_runme.go +++ b/Examples/test-suite/go/director_classic_runme.go @@ -1,7 +1,7 @@ package main import "fmt" -import . "./director_classic" +import . "director_classic" type TargetLangPerson struct{} // From Person func (p *TargetLangPerson) Id() string { diff --git a/Examples/test-suite/go/director_default_runme.go b/Examples/test-suite/go/director_default_runme.go index 2f963b239..ac2aace1d 100644 --- a/Examples/test-suite/go/director_default_runme.go +++ b/Examples/test-suite/go/director_default_runme.go @@ -1,6 +1,6 @@ package main -import . "./director_default" +import . "director_default" func main() { NewFoo() diff --git a/Examples/test-suite/go/director_detect_runme.go b/Examples/test-suite/go/director_detect_runme.go index 9f1ad94a9..0c3c95fdc 100644 --- a/Examples/test-suite/go/director_detect_runme.go +++ b/Examples/test-suite/go/director_detect_runme.go @@ -1,6 +1,6 @@ package main -import "./director_detect" +import "director_detect" type MyBar struct { val int diff --git a/Examples/test-suite/go/director_enum_runme.go b/Examples/test-suite/go/director_enum_runme.go index 5653fda40..002d425d2 100644 --- a/Examples/test-suite/go/director_enum_runme.go +++ b/Examples/test-suite/go/director_enum_runme.go @@ -1,6 +1,6 @@ package main -import "./director_enum" +import "director_enum" type MyFoo struct{} // From director_enum.Foo func (p *MyFoo) Say_hi(val director_enum.EnumDirectorHello) director_enum.EnumDirectorHello { diff --git a/Examples/test-suite/go/director_exception_runme.go b/Examples/test-suite/go/director_exception_runme.go index 29df3e40b..55231ff16 100644 --- a/Examples/test-suite/go/director_exception_runme.go +++ b/Examples/test-suite/go/director_exception_runme.go @@ -1,6 +1,6 @@ package main -import . "./director_exception" +import . "director_exception" type Exception struct { msg string diff --git a/Examples/test-suite/go/director_extend_runme.go b/Examples/test-suite/go/director_extend_runme.go index 70e2ab41b..27e55b997 100644 --- a/Examples/test-suite/go/director_extend_runme.go +++ b/Examples/test-suite/go/director_extend_runme.go @@ -5,7 +5,7 @@ package main -import . "./director_extend" +import . "director_extend" func main() { m := NewSpObject() diff --git a/Examples/test-suite/go/director_finalizer_runme.go b/Examples/test-suite/go/director_finalizer_runme.go index 96fcf860e..d36a4ba33 100644 --- a/Examples/test-suite/go/director_finalizer_runme.go +++ b/Examples/test-suite/go/director_finalizer_runme.go @@ -1,6 +1,6 @@ package main -import . "./director_finalizer" +import . "director_finalizer" type MyFoo struct{} // From Foo func DeleteMyFoo(p Foo) { diff --git a/Examples/test-suite/go/director_frob_runme.go b/Examples/test-suite/go/director_frob_runme.go index a6afedf69..3985eb14b 100644 --- a/Examples/test-suite/go/director_frob_runme.go +++ b/Examples/test-suite/go/director_frob_runme.go @@ -1,6 +1,6 @@ package main -import . "./director_frob" +import . "director_frob" func main() { foo := NewBravo() diff --git a/Examples/test-suite/go/director_nested_runme.go b/Examples/test-suite/go/director_nested_runme.go index 2d3bc77e1..a1193ad59 100644 --- a/Examples/test-suite/go/director_nested_runme.go +++ b/Examples/test-suite/go/director_nested_runme.go @@ -1,6 +1,6 @@ package main -import . "./director_nested" +import . "director_nested" type A struct{} // From FooBar_int func (p *A) Do_step() string { diff --git a/Examples/test-suite/go/director_profile_runme.go b/Examples/test-suite/go/director_profile_runme.go index 87edcbe26..a9bc7934b 100644 --- a/Examples/test-suite/go/director_profile_runme.go +++ b/Examples/test-suite/go/director_profile_runme.go @@ -1,7 +1,7 @@ package main import "fmt" -import "./director_profile" +import "director_profile" type MyB struct{} // From director_profile.B func (p *MyB) Vfi(a int) int { diff --git a/Examples/test-suite/go/director_protected_runme.go b/Examples/test-suite/go/director_protected_runme.go index 24adfe7bd..bfd50c6b2 100644 --- a/Examples/test-suite/go/director_protected_runme.go +++ b/Examples/test-suite/go/director_protected_runme.go @@ -1,6 +1,6 @@ package main -import . "./director_protected" +import . "director_protected" type FooBar struct{} // From Bar func (p *FooBar) Ping() string { diff --git a/Examples/test-suite/go/director_string_runme.go b/Examples/test-suite/go/director_string_runme.go index c5201ab96..f4f9cc150 100644 --- a/Examples/test-suite/go/director_string_runme.go +++ b/Examples/test-suite/go/director_string_runme.go @@ -1,6 +1,6 @@ package main -import . "./director_string" +import . "director_string" type B struct { // From A abi A diff --git a/Examples/test-suite/go/director_unroll_runme.go b/Examples/test-suite/go/director_unroll_runme.go index 6d2894a72..6a919f656 100644 --- a/Examples/test-suite/go/director_unroll_runme.go +++ b/Examples/test-suite/go/director_unroll_runme.go @@ -1,6 +1,6 @@ package main -import "./director_unroll" +import "director_unroll" type MyFoo struct{} // From director_unroll.Foo func (p *MyFoo) Ping() string { diff --git a/Examples/test-suite/go/disown_runme.go b/Examples/test-suite/go/disown_runme.go index 3e853de59..4484515fd 100644 --- a/Examples/test-suite/go/disown_runme.go +++ b/Examples/test-suite/go/disown_runme.go @@ -1,6 +1,6 @@ package main -import . "./disown" +import . "disown" func main() { a := NewA() diff --git a/Examples/test-suite/go/dynamic_cast_runme.go b/Examples/test-suite/go/dynamic_cast_runme.go index 476734805..46ba23698 100644 --- a/Examples/test-suite/go/dynamic_cast_runme.go +++ b/Examples/test-suite/go/dynamic_cast_runme.go @@ -1,6 +1,6 @@ package main -import "./dynamic_cast" +import "dynamic_cast" func main() { f := dynamic_cast.NewFoo() diff --git a/Examples/test-suite/go/empty_c_runme.go b/Examples/test-suite/go/empty_c_runme.go index 831a56118..1a1bd9cc5 100644 --- a/Examples/test-suite/go/empty_c_runme.go +++ b/Examples/test-suite/go/empty_c_runme.go @@ -1,6 +1,6 @@ package main -import _ "./empty_c" +import _ "empty_c" func main() { } diff --git a/Examples/test-suite/go/empty_runme.go b/Examples/test-suite/go/empty_runme.go index f74285cb0..681a6f3ad 100644 --- a/Examples/test-suite/go/empty_runme.go +++ b/Examples/test-suite/go/empty_runme.go @@ -1,6 +1,6 @@ package main -import _ "./empty" +import _ "empty" func main() { } diff --git a/Examples/test-suite/go/enum_template_runme.go b/Examples/test-suite/go/enum_template_runme.go index 269fe7d5b..c60a452d7 100644 --- a/Examples/test-suite/go/enum_template_runme.go +++ b/Examples/test-suite/go/enum_template_runme.go @@ -1,6 +1,6 @@ package main -import "./enum_template" +import "enum_template" func main() { if enum_template.MakeETest() != 1 { diff --git a/Examples/test-suite/go/enums_runme.go b/Examples/test-suite/go/enums_runme.go index ab193f74b..7a528b3e2 100644 --- a/Examples/test-suite/go/enums_runme.go +++ b/Examples/test-suite/go/enums_runme.go @@ -1,6 +1,6 @@ package main -import "./enums" +import "enums" func main() { enums.Bar2(1) diff --git a/Examples/test-suite/go/exception_order_runme.go b/Examples/test-suite/go/exception_order_runme.go index 626a826f8..21dcff312 100644 --- a/Examples/test-suite/go/exception_order_runme.go +++ b/Examples/test-suite/go/exception_order_runme.go @@ -1,7 +1,7 @@ package main import "strings" -import . "./exception_order" +import . "exception_order" func main() { a := NewA() diff --git a/Examples/test-suite/go/extend_placement_runme.go b/Examples/test-suite/go/extend_placement_runme.go index efa776e31..253ec6618 100644 --- a/Examples/test-suite/go/extend_placement_runme.go +++ b/Examples/test-suite/go/extend_placement_runme.go @@ -1,6 +1,6 @@ package main -import "./extend_placement" +import "extend_placement" func main() { foo := extend_placement.NewFoo() diff --git a/Examples/test-suite/go/extend_template_ns_runme.go b/Examples/test-suite/go/extend_template_ns_runme.go index 164a31b26..d005172a4 100644 --- a/Examples/test-suite/go/extend_template_ns_runme.go +++ b/Examples/test-suite/go/extend_template_ns_runme.go @@ -1,6 +1,6 @@ package main -import . "./extend_template_ns" +import . "extend_template_ns" func main() { f := NewFoo_One() diff --git a/Examples/test-suite/go/extend_template_runme.go b/Examples/test-suite/go/extend_template_runme.go index 5adb4b3c2..a5c4da4e1 100644 --- a/Examples/test-suite/go/extend_template_runme.go +++ b/Examples/test-suite/go/extend_template_runme.go @@ -1,6 +1,6 @@ package main -import "./extend_template" +import "extend_template" func main() { f := extend_template.NewFoo_0() diff --git a/Examples/test-suite/go/extend_variable_runme.go b/Examples/test-suite/go/extend_variable_runme.go index c6428c467..9425aee4d 100644 --- a/Examples/test-suite/go/extend_variable_runme.go +++ b/Examples/test-suite/go/extend_variable_runme.go @@ -1,6 +1,6 @@ package main -import . "./extend_variable" +import . "extend_variable" func main() { if FooBar != 42 { diff --git a/Examples/test-suite/go/extern_c_runme.go b/Examples/test-suite/go/extern_c_runme.go index 0fb5b21cc..9bc2cd0cc 100644 --- a/Examples/test-suite/go/extern_c_runme.go +++ b/Examples/test-suite/go/extern_c_runme.go @@ -1,6 +1,6 @@ package main -import "./extern_c" +import "extern_c" func main() { extern_c.RealFunction(2) diff --git a/Examples/test-suite/go/friends_runme.go b/Examples/test-suite/go/friends_runme.go index 9f223fcac..2e34a4db0 100644 --- a/Examples/test-suite/go/friends_runme.go +++ b/Examples/test-suite/go/friends_runme.go @@ -1,6 +1,6 @@ package main -import "./friends" +import "friends" func main() { a := friends.NewA(2) diff --git a/Examples/test-suite/go/fvirtual_runme.go b/Examples/test-suite/go/fvirtual_runme.go index 8810d5cbb..86ef90f18 100644 --- a/Examples/test-suite/go/fvirtual_runme.go +++ b/Examples/test-suite/go/fvirtual_runme.go @@ -1,6 +1,6 @@ package main -import . "./fvirtual" +import . "fvirtual" func main() { sw := NewNodeSwitch() diff --git a/Examples/test-suite/go/global_ns_arg_runme.go b/Examples/test-suite/go/global_ns_arg_runme.go index ece779c9c..e86aa6747 100644 --- a/Examples/test-suite/go/global_ns_arg_runme.go +++ b/Examples/test-suite/go/global_ns_arg_runme.go @@ -1,6 +1,6 @@ package main -import . "./global_ns_arg" +import . "global_ns_arg" func main() { Foo(1) diff --git a/Examples/test-suite/go/go_director_inout_runme.go b/Examples/test-suite/go/go_director_inout_runme.go index 9b9df318e..e6768a465 100644 --- a/Examples/test-suite/go/go_director_inout_runme.go +++ b/Examples/test-suite/go/go_director_inout_runme.go @@ -1,7 +1,7 @@ package main import ( - wrap "./go_director_inout" + wrap "go_director_inout" ) type GoMyClass struct {} diff --git a/Examples/test-suite/go/go_inout_runme.go b/Examples/test-suite/go/go_inout_runme.go index 9aa0cd0c5..4599aa104 100644 --- a/Examples/test-suite/go/go_inout_runme.go +++ b/Examples/test-suite/go/go_inout_runme.go @@ -5,7 +5,7 @@ import ( "fmt" "reflect" - "./go_inout" + "go_inout" ) type S struct { diff --git a/Examples/test-suite/go/go_subdir_import_runme.go b/Examples/test-suite/go/go_subdir_import_runme.go index f90a6eb54..a040c993f 100644 --- a/Examples/test-suite/go/go_subdir_import_runme.go +++ b/Examples/test-suite/go/go_subdir_import_runme.go @@ -1,9 +1,9 @@ package main import ( - "go_subdir_import_a" - "testdir/go_subdir_import/go_subdir_import_b" - "testdir/go_subdir_import/go_subdir_import_c" + "swigtests/go_subdir_import_a" + "swigtests/testdir/go_subdir_import/go_subdir_import_b" + "swigtests/testdir/go_subdir_import/go_subdir_import_c" ) func main() { diff --git a/Examples/test-suite/go/grouping_runme.go b/Examples/test-suite/go/grouping_runme.go index c63d6fb12..f808e1286 100644 --- a/Examples/test-suite/go/grouping_runme.go +++ b/Examples/test-suite/go/grouping_runme.go @@ -1,6 +1,6 @@ package main -import "./grouping" +import "grouping" func main() { x := grouping.Test1(42) diff --git a/Examples/test-suite/go/import_nomodule_runme.go b/Examples/test-suite/go/import_nomodule_runme.go index a6bbd7de5..48592df25 100644 --- a/Examples/test-suite/go/import_nomodule_runme.go +++ b/Examples/test-suite/go/import_nomodule_runme.go @@ -1,6 +1,6 @@ package main -import . "./import_nomodule" +import . "import_nomodule" func main() { f := Create_Foo() diff --git a/Examples/test-suite/go/imports_runme.go b/Examples/test-suite/go/imports_runme.go index 896036cbf..a67ae407b 100644 --- a/Examples/test-suite/go/imports_runme.go +++ b/Examples/test-suite/go/imports_runme.go @@ -2,8 +2,8 @@ package main -import "imports_b" -import "imports_a" +import "swigtests/imports_b" +import "swigtests/imports_a" func main() { x := imports_b.NewB() diff --git a/Examples/test-suite/go/inctest_runme.go b/Examples/test-suite/go/inctest_runme.go index f8a2c116c..3148abcd2 100644 --- a/Examples/test-suite/go/inctest_runme.go +++ b/Examples/test-suite/go/inctest_runme.go @@ -1,6 +1,6 @@ package main -import "./inctest" +import "inctest" func main() { inctest.NewA() diff --git a/Examples/test-suite/go/inherit_member_runme.go b/Examples/test-suite/go/inherit_member_runme.go index 599a0eb56..6fd70cf80 100644 --- a/Examples/test-suite/go/inherit_member_runme.go +++ b/Examples/test-suite/go/inherit_member_runme.go @@ -1,6 +1,6 @@ package main -import wrap "./inherit_member" +import wrap "inherit_member" func main() { s := wrap.NewChild() diff --git a/Examples/test-suite/go/inherit_missing_runme.go b/Examples/test-suite/go/inherit_missing_runme.go index ba9a2a516..c70c48306 100644 --- a/Examples/test-suite/go/inherit_missing_runme.go +++ b/Examples/test-suite/go/inherit_missing_runme.go @@ -1,6 +1,6 @@ package main -import "./inherit_missing" +import "inherit_missing" func main() { a := inherit_missing.New_Foo() diff --git a/Examples/test-suite/go/input_runme.go b/Examples/test-suite/go/input_runme.go index 207bdaa28..ddc2992fe 100644 --- a/Examples/test-suite/go/input_runme.go +++ b/Examples/test-suite/go/input_runme.go @@ -1,6 +1,6 @@ package main -import . "./input" +import . "input" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/keyword_rename_c_runme.go b/Examples/test-suite/go/keyword_rename_c_runme.go index 425e38a26..26f2ea42b 100644 --- a/Examples/test-suite/go/keyword_rename_c_runme.go +++ b/Examples/test-suite/go/keyword_rename_c_runme.go @@ -1,6 +1,6 @@ package main -import "./keyword_rename_c" +import "keyword_rename_c" func main() { keyword_rename_c.Xgo(1) diff --git a/Examples/test-suite/go/keyword_rename_runme.go b/Examples/test-suite/go/keyword_rename_runme.go index e36bc5968..7a40ff83d 100644 --- a/Examples/test-suite/go/keyword_rename_runme.go +++ b/Examples/test-suite/go/keyword_rename_runme.go @@ -1,6 +1,6 @@ package main -import "./keyword_rename" +import "keyword_rename" func main() { keyword_rename.Xgo(1) diff --git a/Examples/test-suite/go/li_attribute_runme.go b/Examples/test-suite/go/li_attribute_runme.go index 5d2c3d0c3..b502b8cea 100644 --- a/Examples/test-suite/go/li_attribute_runme.go +++ b/Examples/test-suite/go/li_attribute_runme.go @@ -1,6 +1,6 @@ package main -import "./li_attribute" +import "li_attribute" func main() { aa := li_attribute.NewA(1, 2, 3) diff --git a/Examples/test-suite/go/li_carrays_cpp_runme.go b/Examples/test-suite/go/li_carrays_cpp_runme.go index 7ee0a4103..cfc171284 100644 --- a/Examples/test-suite/go/li_carrays_cpp_runme.go +++ b/Examples/test-suite/go/li_carrays_cpp_runme.go @@ -1,6 +1,6 @@ package main -import . "./li_carrays_cpp" +import . "li_carrays_cpp" func main() { d := NewDoubleArray(10) diff --git a/Examples/test-suite/go/li_carrays_runme.go b/Examples/test-suite/go/li_carrays_runme.go index 0cbe92cd8..9128bbfd1 100644 --- a/Examples/test-suite/go/li_carrays_runme.go +++ b/Examples/test-suite/go/li_carrays_runme.go @@ -1,6 +1,6 @@ package main -import . "./li_carrays" +import . "li_carrays" func main() { d := NewDoubleArray(10) diff --git a/Examples/test-suite/go/li_cdata_cpp_runme.go b/Examples/test-suite/go/li_cdata_cpp_runme.go index 42a0ebd08..daa5384f7 100644 --- a/Examples/test-suite/go/li_cdata_cpp_runme.go +++ b/Examples/test-suite/go/li_cdata_cpp_runme.go @@ -1,6 +1,6 @@ package main -import . "./li_cdata_cpp" +import . "li_cdata_cpp" func main() { s := "ABC abc" diff --git a/Examples/test-suite/go/li_cdata_runme.go b/Examples/test-suite/go/li_cdata_runme.go index f71a3a2c3..9458dab43 100644 --- a/Examples/test-suite/go/li_cdata_runme.go +++ b/Examples/test-suite/go/li_cdata_runme.go @@ -1,6 +1,6 @@ package main -import . "./li_cdata" +import . "li_cdata" func main() { s := "ABC abc" diff --git a/Examples/test-suite/go/li_cmalloc_runme.go b/Examples/test-suite/go/li_cmalloc_runme.go index 45f47b45f..5b9f9704a 100644 --- a/Examples/test-suite/go/li_cmalloc_runme.go +++ b/Examples/test-suite/go/li_cmalloc_runme.go @@ -1,6 +1,6 @@ package main -import . "./li_cmalloc" +import . "li_cmalloc" func main() { p := Malloc_int() diff --git a/Examples/test-suite/go/li_cpointer_cpp_runme.go b/Examples/test-suite/go/li_cpointer_cpp_runme.go index e2f5a59d1..0de57c624 100644 --- a/Examples/test-suite/go/li_cpointer_cpp_runme.go +++ b/Examples/test-suite/go/li_cpointer_cpp_runme.go @@ -1,6 +1,6 @@ package main -import . "./li_cpointer_cpp" +import . "li_cpointer_cpp" func main() { p := New_intp() diff --git a/Examples/test-suite/go/li_cpointer_runme.go b/Examples/test-suite/go/li_cpointer_runme.go index 57493b122..0fe29e77d 100644 --- a/Examples/test-suite/go/li_cpointer_runme.go +++ b/Examples/test-suite/go/li_cpointer_runme.go @@ -1,6 +1,6 @@ package main -import . "./li_cpointer" +import . "li_cpointer" func main() { p := New_intp() diff --git a/Examples/test-suite/go/li_std_map_runme.go b/Examples/test-suite/go/li_std_map_runme.go index 66e74dd60..5c5cc2e4c 100644 --- a/Examples/test-suite/go/li_std_map_runme.go +++ b/Examples/test-suite/go/li_std_map_runme.go @@ -1,6 +1,6 @@ package main -import "./li_std_map" +import "li_std_map" func main() { a1 := li_std_map.NewA(3) diff --git a/Examples/test-suite/go/li_std_vector_ptr_runme.go b/Examples/test-suite/go/li_std_vector_ptr_runme.go index a9f7fe91c..d66ff19c6 100644 --- a/Examples/test-suite/go/li_std_vector_ptr_runme.go +++ b/Examples/test-suite/go/li_std_vector_ptr_runme.go @@ -1,6 +1,6 @@ package main -import . "./li_std_vector_ptr" +import . "li_std_vector_ptr" import "fmt" func check(val1 int, val2 int) { diff --git a/Examples/test-suite/go/member_pointer_runme.go b/Examples/test-suite/go/member_pointer_runme.go index 9a55bc4b9..731526b75 100644 --- a/Examples/test-suite/go/member_pointer_runme.go +++ b/Examples/test-suite/go/member_pointer_runme.go @@ -3,7 +3,7 @@ package main import "fmt" -import . "./member_pointer" +import . "member_pointer" func check(what string, expected float64, actual float64) { if expected != actual { diff --git a/Examples/test-suite/go/memberin_extend_c_runme.go b/Examples/test-suite/go/memberin_extend_c_runme.go index ec8b11e60..0551acc90 100644 --- a/Examples/test-suite/go/memberin_extend_c_runme.go +++ b/Examples/test-suite/go/memberin_extend_c_runme.go @@ -1,6 +1,6 @@ package main -import "./memberin_extend_c" +import "memberin_extend_c" func main() { t := memberin_extend_c.NewPerson() diff --git a/Examples/test-suite/go/minherit_runme.go b/Examples/test-suite/go/minherit_runme.go index c69fe92c1..9b7873cb0 100644 --- a/Examples/test-suite/go/minherit_runme.go +++ b/Examples/test-suite/go/minherit_runme.go @@ -1,7 +1,7 @@ package main import "fmt" -import "./minherit" +import "minherit" func main() { a := minherit.NewFoo() diff --git a/Examples/test-suite/go/mod_runme.go b/Examples/test-suite/go/mod_runme.go index 581c83918..8d894db8d 100644 --- a/Examples/test-suite/go/mod_runme.go +++ b/Examples/test-suite/go/mod_runme.go @@ -1,7 +1,7 @@ package main -import "mod_a" -import "mod_b" +import "swigtests/mod_a" +import "swigtests/mod_b" func main() { c := mod_b.NewC() diff --git a/Examples/test-suite/go/multi_import_runme.go b/Examples/test-suite/go/multi_import_runme.go index 973af1e7b..f30913c6d 100644 --- a/Examples/test-suite/go/multi_import_runme.go +++ b/Examples/test-suite/go/multi_import_runme.go @@ -1,7 +1,7 @@ package main -import "multi_import_a" -import "multi_import_b" +import "swigtests/multi_import_a" +import "swigtests/multi_import_b" func main() { x := multi_import_b.NewXXX() diff --git a/Examples/test-suite/go/namespace_class_runme.go b/Examples/test-suite/go/namespace_class_runme.go index 2ed5567f7..4c240b6a4 100644 --- a/Examples/test-suite/go/namespace_class_runme.go +++ b/Examples/test-suite/go/namespace_class_runme.go @@ -1,6 +1,6 @@ package main -import . "./namespace_class" +import . "namespace_class" func main() { EulerT3DToFrame(1, 1, 1) diff --git a/Examples/test-suite/go/namespace_typemap_runme.go b/Examples/test-suite/go/namespace_typemap_runme.go index 056da1567..47e2b64f1 100644 --- a/Examples/test-suite/go/namespace_typemap_runme.go +++ b/Examples/test-suite/go/namespace_typemap_runme.go @@ -1,6 +1,6 @@ package main -import . "./namespace_typemap" +import . "namespace_typemap" func main() { if Stest1("hello") != "hello" { diff --git a/Examples/test-suite/go/namespace_virtual_method_runme.go b/Examples/test-suite/go/namespace_virtual_method_runme.go index 3f8e774c6..a8cb38bad 100644 --- a/Examples/test-suite/go/namespace_virtual_method_runme.go +++ b/Examples/test-suite/go/namespace_virtual_method_runme.go @@ -1,6 +1,6 @@ package main -import "./namespace_virtual_method" +import "namespace_virtual_method" func main() { _ = namespace_virtual_method.NewSpam() diff --git a/Examples/test-suite/go/naturalvar_runme.go b/Examples/test-suite/go/naturalvar_runme.go index e3723e6ab..ed47e9d2d 100644 --- a/Examples/test-suite/go/naturalvar_runme.go +++ b/Examples/test-suite/go/naturalvar_runme.go @@ -1,6 +1,6 @@ package main -import . "./naturalvar" +import . "naturalvar" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/nested_workaround_runme.go b/Examples/test-suite/go/nested_workaround_runme.go index 5737aaaf7..8b31a7f4b 100644 --- a/Examples/test-suite/go/nested_workaround_runme.go +++ b/Examples/test-suite/go/nested_workaround_runme.go @@ -1,6 +1,6 @@ package main -import . "./nested_workaround" +import . "nested_workaround" func main() { inner := NewInner(5) diff --git a/Examples/test-suite/go/overload_complicated_runme.go b/Examples/test-suite/go/overload_complicated_runme.go index e3911c218..ce9d124c8 100644 --- a/Examples/test-suite/go/overload_complicated_runme.go +++ b/Examples/test-suite/go/overload_complicated_runme.go @@ -1,6 +1,6 @@ package main -import . "./overload_complicated" +import . "overload_complicated" func main() { var pInt *int diff --git a/Examples/test-suite/go/overload_copy_runme.go b/Examples/test-suite/go/overload_copy_runme.go index d35ff70b1..55ec4a333 100644 --- a/Examples/test-suite/go/overload_copy_runme.go +++ b/Examples/test-suite/go/overload_copy_runme.go @@ -1,6 +1,6 @@ package main -import . "./overload_copy" +import . "overload_copy" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/overload_extend2_runme.go b/Examples/test-suite/go/overload_extend2_runme.go index 121506734..db790989c 100644 --- a/Examples/test-suite/go/overload_extend2_runme.go +++ b/Examples/test-suite/go/overload_extend2_runme.go @@ -1,6 +1,6 @@ package main -import "./overload_extend2" +import "overload_extend2" func main() { f := overload_extend2.NewFoo() diff --git a/Examples/test-suite/go/overload_extend_c_runme.go b/Examples/test-suite/go/overload_extend_c_runme.go index e00f0b945..4d3b2b6e1 100644 --- a/Examples/test-suite/go/overload_extend_c_runme.go +++ b/Examples/test-suite/go/overload_extend_c_runme.go @@ -1,6 +1,6 @@ package main -import "./overload_extend_c" +import "overload_extend_c" func main() { f := overload_extend_c.NewFoo() diff --git a/Examples/test-suite/go/overload_extend_runme.go b/Examples/test-suite/go/overload_extend_runme.go index 1ba541f13..d73d6cf3c 100644 --- a/Examples/test-suite/go/overload_extend_runme.go +++ b/Examples/test-suite/go/overload_extend_runme.go @@ -1,6 +1,6 @@ package main -import "./overload_extend" +import "overload_extend" func main() { f := overload_extend.NewFoo() diff --git a/Examples/test-suite/go/overload_polymorphic_runme.go b/Examples/test-suite/go/overload_polymorphic_runme.go index 46f837f49..12b9777e6 100644 --- a/Examples/test-suite/go/overload_polymorphic_runme.go +++ b/Examples/test-suite/go/overload_polymorphic_runme.go @@ -1,6 +1,6 @@ package main -import "./overload_polymorphic" +import "overload_polymorphic" func main(){ t := overload_polymorphic.NewDerived() diff --git a/Examples/test-suite/go/overload_rename_runme.go b/Examples/test-suite/go/overload_rename_runme.go index dca5843c3..3bd4a69c5 100644 --- a/Examples/test-suite/go/overload_rename_runme.go +++ b/Examples/test-suite/go/overload_rename_runme.go @@ -1,6 +1,6 @@ package main -import "./overload_rename" +import "overload_rename" func main() { _ = overload_rename.NewFoo(float32(1)) diff --git a/Examples/test-suite/go/overload_simple_runme.go b/Examples/test-suite/go/overload_simple_runme.go index 5f6d0558b..3eb859bac 100644 --- a/Examples/test-suite/go/overload_simple_runme.go +++ b/Examples/test-suite/go/overload_simple_runme.go @@ -1,6 +1,6 @@ package main -import . "./overload_simple" +import . "overload_simple" func main() { if Foo(3) != "foo:int" { diff --git a/Examples/test-suite/go/overload_subtype_runme.go b/Examples/test-suite/go/overload_subtype_runme.go index dc56d1ca7..45d5a025f 100644 --- a/Examples/test-suite/go/overload_subtype_runme.go +++ b/Examples/test-suite/go/overload_subtype_runme.go @@ -1,6 +1,6 @@ package main -import . "./overload_subtype" +import . "overload_subtype" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/overload_template_fast_runme.go b/Examples/test-suite/go/overload_template_fast_runme.go index b80cb7dd4..63809c0ff 100644 --- a/Examples/test-suite/go/overload_template_fast_runme.go +++ b/Examples/test-suite/go/overload_template_fast_runme.go @@ -1,6 +1,6 @@ package main -import . "./overload_template_fast" +import . "overload_template_fast" func main() { _ = Foo() diff --git a/Examples/test-suite/go/overload_template_runme.go b/Examples/test-suite/go/overload_template_runme.go index 53e1def1b..f3a08ecd6 100644 --- a/Examples/test-suite/go/overload_template_runme.go +++ b/Examples/test-suite/go/overload_template_runme.go @@ -1,6 +1,6 @@ package main -import . "./overload_template" +import . "overload_template" func main() { _ = Foo() diff --git a/Examples/test-suite/go/preproc_runme.go b/Examples/test-suite/go/preproc_runme.go index a15062241..3c55aae72 100644 --- a/Examples/test-suite/go/preproc_runme.go +++ b/Examples/test-suite/go/preproc_runme.go @@ -1,6 +1,6 @@ package main -import "./preproc" +import "preproc" func main() { if preproc.GetEndif() != 1 { diff --git a/Examples/test-suite/go/primitive_ref_runme.go b/Examples/test-suite/go/primitive_ref_runme.go index 973806955..a1de2f8a5 100644 --- a/Examples/test-suite/go/primitive_ref_runme.go +++ b/Examples/test-suite/go/primitive_ref_runme.go @@ -1,6 +1,6 @@ package main -import . "./primitive_ref" +import . "primitive_ref" func main() { if Ref_int(3) != 3 { diff --git a/Examples/test-suite/go/profiletest_runme.go b/Examples/test-suite/go/profiletest_runme.go index 30b6cee69..c2b922ba3 100644 --- a/Examples/test-suite/go/profiletest_runme.go +++ b/Examples/test-suite/go/profiletest_runme.go @@ -1,7 +1,7 @@ package main import "fmt" -import "./profiletest" +import "profiletest" func main() { a := profiletest.NewA() diff --git a/Examples/test-suite/go/refcount_runme.go b/Examples/test-suite/go/refcount_runme.go index fdb271cc6..07d407273 100644 --- a/Examples/test-suite/go/refcount_runme.go +++ b/Examples/test-suite/go/refcount_runme.go @@ -1,6 +1,6 @@ package main -import . "./refcount" +import . "refcount" // very innocent example diff --git a/Examples/test-suite/go/reference_global_vars_runme.go b/Examples/test-suite/go/reference_global_vars_runme.go index b8cbb304a..908358f95 100644 --- a/Examples/test-suite/go/reference_global_vars_runme.go +++ b/Examples/test-suite/go/reference_global_vars_runme.go @@ -1,6 +1,6 @@ package main -import . "./reference_global_vars" +import . "reference_global_vars" func main() { // const class reference variable diff --git a/Examples/test-suite/go/rename_scope_runme.go b/Examples/test-suite/go/rename_scope_runme.go index 995f8c64d..13bd3f178 100644 --- a/Examples/test-suite/go/rename_scope_runme.go +++ b/Examples/test-suite/go/rename_scope_runme.go @@ -1,6 +1,6 @@ package main -import . "./rename_scope" +import . "rename_scope" func main() { a := NewNatural_UP() diff --git a/Examples/test-suite/go/rename_simple_runme.go b/Examples/test-suite/go/rename_simple_runme.go index a63023bd1..bd559ef27 100644 --- a/Examples/test-suite/go/rename_simple_runme.go +++ b/Examples/test-suite/go/rename_simple_runme.go @@ -1,7 +1,7 @@ package main import "fmt" -import . "./rename_simple" +import . "rename_simple" func main() { s := NewNewStruct() diff --git a/Examples/test-suite/go/rename_strip_encoder_runme.go b/Examples/test-suite/go/rename_strip_encoder_runme.go index 1d0bcb660..ae670600c 100644 --- a/Examples/test-suite/go/rename_strip_encoder_runme.go +++ b/Examples/test-suite/go/rename_strip_encoder_runme.go @@ -1,6 +1,6 @@ package main -import . "./rename_strip_encoder" +import . "rename_strip_encoder" func main() { _ = NewSomeWidget() diff --git a/Examples/test-suite/go/ret_by_value_runme.go b/Examples/test-suite/go/ret_by_value_runme.go index 44743d2b7..9659d21e9 100644 --- a/Examples/test-suite/go/ret_by_value_runme.go +++ b/Examples/test-suite/go/ret_by_value_runme.go @@ -1,6 +1,6 @@ package main -import "./ret_by_value" +import "ret_by_value" func main() { a := ret_by_value.Get_test() diff --git a/Examples/test-suite/go/return_const_value_runme.go b/Examples/test-suite/go/return_const_value_runme.go index 790921b74..aadb1265e 100644 --- a/Examples/test-suite/go/return_const_value_runme.go +++ b/Examples/test-suite/go/return_const_value_runme.go @@ -1,6 +1,6 @@ package main -import "./return_const_value" +import "return_const_value" func main() { p := return_const_value.Foo_ptrGetPtr() diff --git a/Examples/test-suite/go/smart_pointer_extend_runme.go b/Examples/test-suite/go/smart_pointer_extend_runme.go index ee5ce0538..a851e26b7 100644 --- a/Examples/test-suite/go/smart_pointer_extend_runme.go +++ b/Examples/test-suite/go/smart_pointer_extend_runme.go @@ -1,6 +1,6 @@ package main -import . "./smart_pointer_extend" +import . "smart_pointer_extend" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/smart_pointer_member_runme.go b/Examples/test-suite/go/smart_pointer_member_runme.go index bf09fe5fc..e7fe7c4c2 100644 --- a/Examples/test-suite/go/smart_pointer_member_runme.go +++ b/Examples/test-suite/go/smart_pointer_member_runme.go @@ -1,7 +1,7 @@ package main import "fmt" -import . "./smart_pointer_member" +import . "smart_pointer_member" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/smart_pointer_multi_runme.go b/Examples/test-suite/go/smart_pointer_multi_runme.go index d1a5f92f4..7c76061af 100644 --- a/Examples/test-suite/go/smart_pointer_multi_runme.go +++ b/Examples/test-suite/go/smart_pointer_multi_runme.go @@ -1,6 +1,6 @@ package main -import . "./smart_pointer_multi" +import . "smart_pointer_multi" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/smart_pointer_multi_typedef_runme.go b/Examples/test-suite/go/smart_pointer_multi_typedef_runme.go index f71740bbb..e584cf7a2 100644 --- a/Examples/test-suite/go/smart_pointer_multi_typedef_runme.go +++ b/Examples/test-suite/go/smart_pointer_multi_typedef_runme.go @@ -1,6 +1,6 @@ package main -import . "./smart_pointer_multi_typedef" +import . "smart_pointer_multi_typedef" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/smart_pointer_overload_runme.go b/Examples/test-suite/go/smart_pointer_overload_runme.go index 5ffeae17c..9481554f0 100644 --- a/Examples/test-suite/go/smart_pointer_overload_runme.go +++ b/Examples/test-suite/go/smart_pointer_overload_runme.go @@ -1,6 +1,6 @@ package main -import . "./smart_pointer_overload" +import . "smart_pointer_overload" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/smart_pointer_rename_runme.go b/Examples/test-suite/go/smart_pointer_rename_runme.go index 678c305c8..44841f5e6 100644 --- a/Examples/test-suite/go/smart_pointer_rename_runme.go +++ b/Examples/test-suite/go/smart_pointer_rename_runme.go @@ -1,6 +1,6 @@ package main -import . "./smart_pointer_rename" +import . "smart_pointer_rename" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/smart_pointer_simple_runme.go b/Examples/test-suite/go/smart_pointer_simple_runme.go index 328654225..b468bd2e5 100644 --- a/Examples/test-suite/go/smart_pointer_simple_runme.go +++ b/Examples/test-suite/go/smart_pointer_simple_runme.go @@ -1,6 +1,6 @@ package main -import . "./smart_pointer_simple" +import . "smart_pointer_simple" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/smart_pointer_templatevariables_runme.go b/Examples/test-suite/go/smart_pointer_templatevariables_runme.go index bf58ba52c..6d4ea91de 100644 --- a/Examples/test-suite/go/smart_pointer_templatevariables_runme.go +++ b/Examples/test-suite/go/smart_pointer_templatevariables_runme.go @@ -1,6 +1,6 @@ package main -import . "./smart_pointer_templatevariables" +import . "smart_pointer_templatevariables" func main() { d := NewDiffImContainerPtr_D(Create(1234, 5678)) diff --git a/Examples/test-suite/go/smart_pointer_typedef_runme.go b/Examples/test-suite/go/smart_pointer_typedef_runme.go index a67a0ccda..e89a8b150 100644 --- a/Examples/test-suite/go/smart_pointer_typedef_runme.go +++ b/Examples/test-suite/go/smart_pointer_typedef_runme.go @@ -1,6 +1,6 @@ package main -import . "./smart_pointer_typedef" +import . "smart_pointer_typedef" func main() { f := NewFoo() diff --git a/Examples/test-suite/go/sneaky1_runme.go b/Examples/test-suite/go/sneaky1_runme.go index ee38ae21b..57c779724 100644 --- a/Examples/test-suite/go/sneaky1_runme.go +++ b/Examples/test-suite/go/sneaky1_runme.go @@ -1,6 +1,6 @@ package main -import "./sneaky1" +import "sneaky1" func main() { _ = sneaky1.Add(3, 4) diff --git a/Examples/test-suite/go/special_variable_macros_runme.go b/Examples/test-suite/go/special_variable_macros_runme.go index c4f687ea9..9338e6558 100644 --- a/Examples/test-suite/go/special_variable_macros_runme.go +++ b/Examples/test-suite/go/special_variable_macros_runme.go @@ -1,6 +1,6 @@ package main -import "./special_variable_macros" +import "special_variable_macros" func main() { name := special_variable_macros.NewName() diff --git a/Examples/test-suite/go/static_const_member_2_runme.go b/Examples/test-suite/go/static_const_member_2_runme.go index 0d345c3d6..ff8cbbbcd 100644 --- a/Examples/test-suite/go/static_const_member_2_runme.go +++ b/Examples/test-suite/go/static_const_member_2_runme.go @@ -1,6 +1,6 @@ package main -import . "./static_const_member_2" +import . "static_const_member_2" func main() { _ = NewTest_int() diff --git a/Examples/test-suite/go/struct_initialization_runme.go b/Examples/test-suite/go/struct_initialization_runme.go index 58ac25010..a815bd3f5 100644 --- a/Examples/test-suite/go/struct_initialization_runme.go +++ b/Examples/test-suite/go/struct_initialization_runme.go @@ -1,6 +1,6 @@ package main -import . "./struct_initialization" +import . "struct_initialization" func main() { if GetInstanceC1().GetX() != 10 { diff --git a/Examples/test-suite/go/struct_rename_runme.go b/Examples/test-suite/go/struct_rename_runme.go index 845dac5be..de99fc320 100644 --- a/Examples/test-suite/go/struct_rename_runme.go +++ b/Examples/test-suite/go/struct_rename_runme.go @@ -1,6 +1,6 @@ package main -import "./struct_rename" +import "struct_rename" func main() { _ = struct_rename.NewBar() diff --git a/Examples/test-suite/go/struct_value_runme.go b/Examples/test-suite/go/struct_value_runme.go index d0b60bd23..3b5e5c1dc 100644 --- a/Examples/test-suite/go/struct_value_runme.go +++ b/Examples/test-suite/go/struct_value_runme.go @@ -1,6 +1,6 @@ package main -import "./struct_value" +import "struct_value" func main() { b := struct_value.NewBar() diff --git a/Examples/test-suite/go/template_default_arg_runme.go b/Examples/test-suite/go/template_default_arg_runme.go index 3d9346b05..d67e63fa7 100644 --- a/Examples/test-suite/go/template_default_arg_runme.go +++ b/Examples/test-suite/go/template_default_arg_runme.go @@ -1,6 +1,6 @@ package main -import "./template_default_arg" +import "template_default_arg" func main() { helloInt := template_default_arg.NewHello_int() diff --git a/Examples/test-suite/go/template_extend1_runme.go b/Examples/test-suite/go/template_extend1_runme.go index 5d6d376f5..0912fa6ed 100644 --- a/Examples/test-suite/go/template_extend1_runme.go +++ b/Examples/test-suite/go/template_extend1_runme.go @@ -1,6 +1,6 @@ package main -import "./template_extend1" +import "template_extend1" func main() { a := template_extend1.NewLBaz() diff --git a/Examples/test-suite/go/template_extend2_runme.go b/Examples/test-suite/go/template_extend2_runme.go index 312410e27..ced3d93cc 100644 --- a/Examples/test-suite/go/template_extend2_runme.go +++ b/Examples/test-suite/go/template_extend2_runme.go @@ -1,6 +1,6 @@ package main -import "./template_extend2" +import "template_extend2" func main() { a := template_extend2.NewLBaz() diff --git a/Examples/test-suite/go/template_inherit_runme.go b/Examples/test-suite/go/template_inherit_runme.go index c0aca77c4..a8d5126dc 100644 --- a/Examples/test-suite/go/template_inherit_runme.go +++ b/Examples/test-suite/go/template_inherit_runme.go @@ -1,6 +1,6 @@ package main -import . "./template_inherit" +import . "template_inherit" func main() { a := NewFooInt() diff --git a/Examples/test-suite/go/template_ns4_runme.go b/Examples/test-suite/go/template_ns4_runme.go index 4caf8f587..6c658ec97 100644 --- a/Examples/test-suite/go/template_ns4_runme.go +++ b/Examples/test-suite/go/template_ns4_runme.go @@ -1,6 +1,6 @@ package main -import . "./template_ns4" +import . "template_ns4" func main() { d := Make_Class_DD() diff --git a/Examples/test-suite/go/template_ns_runme.go b/Examples/test-suite/go/template_ns_runme.go index 6385eccf9..cfc56fa3c 100644 --- a/Examples/test-suite/go/template_ns_runme.go +++ b/Examples/test-suite/go/template_ns_runme.go @@ -1,6 +1,6 @@ package main -import . "./template_ns" +import . "template_ns" func main() { p1 := NewPairii(2, 3) diff --git a/Examples/test-suite/go/template_opaque_runme.go b/Examples/test-suite/go/template_opaque_runme.go index 201f7ba16..71701df53 100644 --- a/Examples/test-suite/go/template_opaque_runme.go +++ b/Examples/test-suite/go/template_opaque_runme.go @@ -1,6 +1,6 @@ package main -import "./template_opaque" +import "template_opaque" func main() { v := template_opaque.NewOpaqueVectorType(int64(10)) diff --git a/Examples/test-suite/go/template_ref_type_runme.go b/Examples/test-suite/go/template_ref_type_runme.go index e4bf626fb..a01ce3d31 100644 --- a/Examples/test-suite/go/template_ref_type_runme.go +++ b/Examples/test-suite/go/template_ref_type_runme.go @@ -1,6 +1,6 @@ package main -import "./template_ref_type" +import "template_ref_type" func main() { xr := template_ref_type.NewXC() diff --git a/Examples/test-suite/go/template_rename_runme.go b/Examples/test-suite/go/template_rename_runme.go index 757ac7355..6e04f8845 100644 --- a/Examples/test-suite/go/template_rename_runme.go +++ b/Examples/test-suite/go/template_rename_runme.go @@ -1,6 +1,6 @@ package main -import "./template_rename" +import "template_rename" func main() { i := template_rename.NewIFoo() diff --git a/Examples/test-suite/go/template_static_runme.go b/Examples/test-suite/go/template_static_runme.go index 7fa50760a..f10ea78f7 100644 --- a/Examples/test-suite/go/template_static_runme.go +++ b/Examples/test-suite/go/template_static_runme.go @@ -1,6 +1,6 @@ package main -import . "./template_static" +import . "template_static" func main() { FooBar_double(1) diff --git a/Examples/test-suite/go/template_tbase_template_runme.go b/Examples/test-suite/go/template_tbase_template_runme.go index 9a52e2fac..e1c46aaf7 100644 --- a/Examples/test-suite/go/template_tbase_template_runme.go +++ b/Examples/test-suite/go/template_tbase_template_runme.go @@ -1,6 +1,6 @@ package main -import . "./template_tbase_template" +import . "template_tbase_template" func main() { a := Make_Class_dd() diff --git a/Examples/test-suite/go/template_type_namespace_runme.go b/Examples/test-suite/go/template_type_namespace_runme.go index a3712ff59..1356f9b08 100644 --- a/Examples/test-suite/go/template_type_namespace_runme.go +++ b/Examples/test-suite/go/template_type_namespace_runme.go @@ -1,6 +1,6 @@ package main -import . "./template_type_namespace" +import . "template_type_namespace" func main() { if Foo().Get(0) == "" { diff --git a/Examples/test-suite/go/template_typedef_cplx3_runme.go b/Examples/test-suite/go/template_typedef_cplx3_runme.go index d616777e0..0a2b31301 100644 --- a/Examples/test-suite/go/template_typedef_cplx3_runme.go +++ b/Examples/test-suite/go/template_typedef_cplx3_runme.go @@ -1,6 +1,6 @@ package main -import . "./template_typedef_cplx3" +import . "template_typedef_cplx3" func main() { // this is OK diff --git a/Examples/test-suite/go/template_typedef_cplx4_runme.go b/Examples/test-suite/go/template_typedef_cplx4_runme.go index 3e536d6f2..d8952cfb6 100644 --- a/Examples/test-suite/go/template_typedef_cplx4_runme.go +++ b/Examples/test-suite/go/template_typedef_cplx4_runme.go @@ -1,6 +1,6 @@ package main -import . "./template_typedef_cplx4" +import . "template_typedef_cplx4" func main() { // this is OK diff --git a/Examples/test-suite/go/threads_exception_runme.go b/Examples/test-suite/go/threads_exception_runme.go index 742a827bd..e3da1dc25 100644 --- a/Examples/test-suite/go/threads_exception_runme.go +++ b/Examples/test-suite/go/threads_exception_runme.go @@ -1,7 +1,7 @@ package main import "strings" -import "./threads_exception" +import "threads_exception" func main() { t := threads_exception.NewTest() diff --git a/Examples/test-suite/go/typedef_class_runme.go b/Examples/test-suite/go/typedef_class_runme.go index ec25162de..d94126d3b 100644 --- a/Examples/test-suite/go/typedef_class_runme.go +++ b/Examples/test-suite/go/typedef_class_runme.go @@ -1,6 +1,6 @@ package main -import "./typedef_class" +import "typedef_class" func main() { a := typedef_class.NewRealA() diff --git a/Examples/test-suite/go/typedef_funcptr_runme.go b/Examples/test-suite/go/typedef_funcptr_runme.go new file mode 100644 index 000000000..9d55f3f04 --- /dev/null +++ b/Examples/test-suite/go/typedef_funcptr_runme.go @@ -0,0 +1,29 @@ +package main + +import . "typedef_funcptr" + +func main() { + a := 100 + b := 10 + + if Do_op(a,b,Addf) != 110 { + panic(0) + } + if Do_op(a,b,Subf) != 90 { + panic(0) + } + + if Do_op_typedef_int(a,b,Addf) != 110 { + panic(0) + } + if Do_op_typedef_int(a,b,Subf) != 90 { + panic(0) + } + + if Do_op_typedef_Integer(a,b,Addf) != 110 { + panic(0) + } + if Do_op_typedef_Integer(a,b,Subf) != 90 { + panic(0) + } +} diff --git a/Examples/test-suite/go/typedef_inherit_runme.go b/Examples/test-suite/go/typedef_inherit_runme.go index 49097999c..7a65569f2 100644 --- a/Examples/test-suite/go/typedef_inherit_runme.go +++ b/Examples/test-suite/go/typedef_inherit_runme.go @@ -1,6 +1,6 @@ package main -import "./typedef_inherit" +import "typedef_inherit" func main() { a := typedef_inherit.NewFoo() diff --git a/Examples/test-suite/go/typedef_scope_runme.go b/Examples/test-suite/go/typedef_scope_runme.go index 1c4314427..af282b16f 100644 --- a/Examples/test-suite/go/typedef_scope_runme.go +++ b/Examples/test-suite/go/typedef_scope_runme.go @@ -1,6 +1,6 @@ package main -import "./typedef_scope" +import "typedef_scope" func main() { b := typedef_scope.NewBar() diff --git a/Examples/test-suite/go/typemap_namespace_runme.go b/Examples/test-suite/go/typemap_namespace_runme.go index 45184fd1e..a2880d4a8 100644 --- a/Examples/test-suite/go/typemap_namespace_runme.go +++ b/Examples/test-suite/go/typemap_namespace_runme.go @@ -1,6 +1,6 @@ package main -import . "./typemap_namespace" +import . "typemap_namespace" func main() { if Test1("hello") != "hello" { diff --git a/Examples/test-suite/go/typemap_ns_using_runme.go b/Examples/test-suite/go/typemap_ns_using_runme.go index 877e44b3a..c4c21cf75 100644 --- a/Examples/test-suite/go/typemap_ns_using_runme.go +++ b/Examples/test-suite/go/typemap_ns_using_runme.go @@ -1,6 +1,6 @@ package main -import "./typemap_ns_using" +import "typemap_ns_using" func main() { if typemap_ns_using.Spam(37) != 37 { diff --git a/Examples/test-suite/go/typemap_out_optimal_runme.go b/Examples/test-suite/go/typemap_out_optimal_runme.go index 7cbd0ad9b..7cc3b38e3 100644 --- a/Examples/test-suite/go/typemap_out_optimal_runme.go +++ b/Examples/test-suite/go/typemap_out_optimal_runme.go @@ -1,6 +1,6 @@ package main -import . "./typemap_out_optimal" +import . "typemap_out_optimal" func main() { SetXXDebug(false) diff --git a/Examples/test-suite/go/typename_runme.go b/Examples/test-suite/go/typename_runme.go index 0bc15f11a..d1665099c 100644 --- a/Examples/test-suite/go/typename_runme.go +++ b/Examples/test-suite/go/typename_runme.go @@ -1,6 +1,6 @@ package main -import "./typename" +import "typename" func main() { f := typename.NewFoo() diff --git a/Examples/test-suite/go/unions_runme.go b/Examples/test-suite/go/unions_runme.go index ba9c27b17..b76ca5c75 100644 --- a/Examples/test-suite/go/unions_runme.go +++ b/Examples/test-suite/go/unions_runme.go @@ -3,7 +3,7 @@ package main -import "./unions" +import "unions" func main() { // Create new instances of SmallStruct and BigStruct for later use diff --git a/Examples/test-suite/go/using1_runme.go b/Examples/test-suite/go/using1_runme.go index 8cc571288..a6a6fa738 100644 --- a/Examples/test-suite/go/using1_runme.go +++ b/Examples/test-suite/go/using1_runme.go @@ -1,6 +1,6 @@ package main -import "./using1" +import "using1" func main() { if using1.Spam(37) != 37 { diff --git a/Examples/test-suite/go/using2_runme.go b/Examples/test-suite/go/using2_runme.go index f679b0c40..f6b8d49b5 100644 --- a/Examples/test-suite/go/using2_runme.go +++ b/Examples/test-suite/go/using2_runme.go @@ -1,6 +1,6 @@ package main -import "./using2" +import "using2" func main() { if using2.Spam(37) != 37 { diff --git a/Examples/test-suite/go/using_composition_runme.go b/Examples/test-suite/go/using_composition_runme.go index 47e245719..712d1fad5 100644 --- a/Examples/test-suite/go/using_composition_runme.go +++ b/Examples/test-suite/go/using_composition_runme.go @@ -1,6 +1,6 @@ package main -import . "./using_composition" +import . "using_composition" func main() { f := NewFooBar() diff --git a/Examples/test-suite/go/using_extend_runme.go b/Examples/test-suite/go/using_extend_runme.go index 830c958e5..27d1ccc62 100644 --- a/Examples/test-suite/go/using_extend_runme.go +++ b/Examples/test-suite/go/using_extend_runme.go @@ -1,6 +1,6 @@ package main -import . "./using_extend" +import . "using_extend" func main() { f := NewFooBar() diff --git a/Examples/test-suite/go/using_inherit_runme.go b/Examples/test-suite/go/using_inherit_runme.go index db29efb64..a88171817 100644 --- a/Examples/test-suite/go/using_inherit_runme.go +++ b/Examples/test-suite/go/using_inherit_runme.go @@ -1,6 +1,6 @@ package main -import . "./using_inherit" +import . "using_inherit" func main() { b := NewBar() diff --git a/Examples/test-suite/go/using_private_runme.go b/Examples/test-suite/go/using_private_runme.go index d683ef856..2da62dc2e 100644 --- a/Examples/test-suite/go/using_private_runme.go +++ b/Examples/test-suite/go/using_private_runme.go @@ -1,6 +1,6 @@ package main -import . "./using_private" +import . "using_private" func main() { f := NewFooBar() diff --git a/Examples/test-suite/go/using_protected_runme.go b/Examples/test-suite/go/using_protected_runme.go index 65edb5001..3fd5029f7 100644 --- a/Examples/test-suite/go/using_protected_runme.go +++ b/Examples/test-suite/go/using_protected_runme.go @@ -1,6 +1,6 @@ package main -import . "./using_protected" +import . "using_protected" func main() { f := NewFooBar() diff --git a/Examples/test-suite/go/varargs_overload_runme.go b/Examples/test-suite/go/varargs_overload_runme.go index 52fc1b0e9..8ce580d65 100644 --- a/Examples/test-suite/go/varargs_overload_runme.go +++ b/Examples/test-suite/go/varargs_overload_runme.go @@ -1,6 +1,6 @@ package main -import "./varargs_overload" +import "varargs_overload" func main() { if varargs_overload.Vararg_over1("Hello") != "Hello" { @@ -35,4 +35,40 @@ func main() { if varargs_overload.Vararg_over4("Hello", 123) != "Hello" { panic(8) } + + + // Same as above but non-vararg function declared first + + if varargs_overload.Vararg_over6("Hello") != "Hello" { + panic(0) + } + if varargs_overload.Vararg_over6(2) != "2" { + panic(1) + } + + if varargs_overload.Vararg_over7("Hello") != "Hello" { + panic(2) + } + if varargs_overload.Vararg_over7(2, 2.2) != "2 2.2" { + panic(3) + } + + if varargs_overload.Vararg_over8("Hello") != "Hello" { + panic(4) + } + if varargs_overload.Vararg_over8(2, 2.2, "hey") != "2 2.2 hey" { + panic(5) + } + + if varargs_overload.Vararg_over9("Hello") != "Hello" { + panic(6) + } + + if varargs_overload.Vararg_over9(123) != "123" { + panic(7) + } + + if varargs_overload.Vararg_over9("Hello", 123) != "Hello" { + panic(8) + } } diff --git a/Examples/test-suite/go/varargs_runme.go b/Examples/test-suite/go/varargs_runme.go index 4009c3ed3..60bd8829a 100644 --- a/Examples/test-suite/go/varargs_runme.go +++ b/Examples/test-suite/go/varargs_runme.go @@ -1,6 +1,6 @@ package main -import "./varargs" +import "varargs" func main() { if varargs.Test("Hello") != "Hello" { diff --git a/Examples/test-suite/go/virtual_derivation_runme.go b/Examples/test-suite/go/virtual_derivation_runme.go index 48a7033a2..4e2c6e585 100644 --- a/Examples/test-suite/go/virtual_derivation_runme.go +++ b/Examples/test-suite/go/virtual_derivation_runme.go @@ -1,6 +1,6 @@ package main -import . "./virtual_derivation" +import . "virtual_derivation" // very innocent example diff --git a/Examples/test-suite/go/virtual_poly_runme.go b/Examples/test-suite/go/virtual_poly_runme.go index 487b371ba..32906b391 100644 --- a/Examples/test-suite/go/virtual_poly_runme.go +++ b/Examples/test-suite/go/virtual_poly_runme.go @@ -1,6 +1,6 @@ package main -import "./virtual_poly" +import "virtual_poly" func main() { d := virtual_poly.NewNDouble(3.5) diff --git a/Examples/test-suite/go/voidtest_runme.go b/Examples/test-suite/go/voidtest_runme.go index 0a685f081..133545cea 100644 --- a/Examples/test-suite/go/voidtest_runme.go +++ b/Examples/test-suite/go/voidtest_runme.go @@ -1,6 +1,6 @@ package main -import "./voidtest" +import "voidtest" func main() { voidtest.Globalfunc() diff --git a/Examples/test-suite/go/wrapmacro_runme.go b/Examples/test-suite/go/wrapmacro_runme.go index dc7e7bf5b..a251a05e8 100644 --- a/Examples/test-suite/go/wrapmacro_runme.go +++ b/Examples/test-suite/go/wrapmacro_runme.go @@ -1,6 +1,6 @@ package main -import "./wrapmacro" +import "wrapmacro" func main() { a := 2 diff --git a/Examples/test-suite/go_subdir_import.list b/Examples/test-suite/go_subdir_import.list index e117d32fa..074c795b3 100644 --- a/Examples/test-suite/go_subdir_import.list +++ b/Examples/test-suite/go_subdir_import.list @@ -1,3 +1,3 @@ testdir/go_subdir_import/go_subdir_import_c -go_subdir_import_b +testdir/go_subdir_import/go_subdir_import_b go_subdir_import_a diff --git a/Examples/test-suite/guile/argout_runme.scm b/Examples/test-suite/guile/argout_runme.scm new file mode 100644 index 000000000..16f2aeb1c --- /dev/null +++ b/Examples/test-suite/guile/argout_runme.scm @@ -0,0 +1,20 @@ +;; tests support for native guile pointers +;; https://www.gnu.org/software/guile/manual/html_node/Void-Pointers-and-Byte-Access.html +(dynamic-call "scm_init_argout_module" (dynamic-link "./libargout")) + +(define initial-value 42) +(define some-s32-data (s32vector initial-value)) + +;; if we're running guile 1.8, then bytevector->pointer won't exist and this +;; test is useless +(if (>= (string->number (major-version)) 2) + (begin + (use-modules (srfi srfi-4) (system foreign)) + + (if (not (= (incp (bytevector->pointer some-s32-data)) initial-value)) + (error "Didn't read s32 data" initial-value some-s32-data)) + + (if (not (= (s32vector-ref some-s32-data 0) (+ initial-value 1))) + (error "Failed to increment s32 data" some-s32-data)))) + +(exit 0) diff --git a/Examples/test-suite/guile/overload_complicated_runme.scm b/Examples/test-suite/guile/overload_complicated_runme.scm index a38fb8afe..0630d4ecc 100644 --- a/Examples/test-suite/guile/overload_complicated_runme.scm +++ b/Examples/test-suite/guile/overload_complicated_runme.scm @@ -14,8 +14,8 @@ (check (=~ (foo 1 2 "bar" 4) 15)) ;; Check second method -(check (=~ (foo 1 2) 4811.4)) -(check (=~ (foo 1 2 3.2) 4797.2)) -(check (=~ (foo 1 2 3.2 #\Q) 4798.2)) +(check (=~ (foo 1 2) 118)) +(check (=~ (foo 1 2 3.2) 104)) +(check (=~ (foo 1 2 3.2 #\Q) 4798)) (exit 0) diff --git a/Examples/test-suite/guile/overload_null_runme.scm b/Examples/test-suite/guile/overload_null_runme.scm new file mode 100644 index 000000000..f764d9c20 --- /dev/null +++ b/Examples/test-suite/guile/overload_null_runme.scm @@ -0,0 +1,53 @@ +;; The SWIG modules have "passive" Linkage, i.e., they don't generate +;; Guile modules (namespaces) but simply put all the bindings into the +;; current module. That's enough for such a simple test. +(dynamic-call "scm_init_overload_null_module" (dynamic-link "./liboverload_null")) + +(define-macro (check form) + `(if (not ,form) + (error "Check failed: " ',form))) + +(define (=~ a b) + (< (abs (- a b)) 1e-8)) + +(define o (new-Overload)) +(define x (new-X)) + +(check (=~ 1 (Overload-byval1 o x))) +(check (=~ 2 (Overload-byval1 o #nil))) + +(check (=~ 3 (Overload-byval2 o #nil))) +(check (=~ 4 (Overload-byval2 o x))) + +(check (=~ 5 (Overload-byref1 o x))) +(check (=~ 6 (Overload-byref1 o #nil))) + +(check (=~ 7 (Overload-byref2 o #nil))) +(check (=~ 8 (Overload-byref2 o x))) + +(check (=~ 9 (Overload-byconstref1 o x))) +(check (=~ 10 (Overload-byconstref1 o #nil))) + +(check (=~ 11 (Overload-byconstref2 o #nil))) +(check (=~ 12 (Overload-byconstref2 o x))) + +; const pointer references +; No SWIGTYPE *const& typemaps for Guile yet +;(check (=~ 13 (Overload-byval1cpr o x))) +;(check (=~ 14 (Overload-byval1cpr o #nil))) + +;(check (=~ 15 (Overload-byval2cpr o #nil))) +;(check (=~ 16 (Overload-byval2cpr o x))) + +; forward class declaration +(check (=~ 17 (Overload-byval1forwardptr o x))) +(check (=~ 18 (Overload-byval1forwardptr o #nil))) + +(check (=~ 19 (Overload-byval2forwardptr o #nil))) +(check (=~ 20 (Overload-byval2forwardptr o x))) + +(check (=~ 21 (Overload-byval1forwardref o x))) + +(check (=~ 22 (Overload-byval2forwardref o x))) + +(exit 0) diff --git a/Examples/test-suite/ignore_parameter.i b/Examples/test-suite/ignore_parameter.i index bc0892c3a..604ee3b84 100644 --- a/Examples/test-suite/ignore_parameter.i +++ b/Examples/test-suite/ignore_parameter.i @@ -8,12 +8,15 @@ %typemap(freearg) char* a ""; // ensure freearg is not generated (needed for Java at least) +%ignore unignorable; + %inline %{ // global function tests char* jaguar(char* a, int b, double c) { return a; } int lotus(char* aa, int bb, double cc) { return bb; } double tvr(char* aaa, int bbb, double ccc) { return ccc; } int ferrari(int bb) { return bb; } +int fiat(int unignorable) { return unignorable; } // member function tests struct SportsCars { @@ -21,6 +24,7 @@ struct SportsCars { int astonmartin(char* aa, int bb, double cc) { return bb; } double bugatti(char* aaa, int bbb, double ccc) { return ccc; } int lamborghini(int bb) { return bb; } + int maseratti(int unignorable) { return unignorable; } }; // constructor tests diff --git a/Examples/test-suite/ignore_template_constructor.i b/Examples/test-suite/ignore_template_constructor.i index 31a5505fb..bdffbec3e 100644 --- a/Examples/test-suite/ignore_template_constructor.i +++ b/Examples/test-suite/ignore_template_constructor.i @@ -1,12 +1,18 @@ %module ignore_template_constructor %include std_vector.i -#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGPERL) || defined(SWIGRUBY) +#if defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGPERL) || defined(SWIGRUBY) #define SWIG_GOOD_VECTOR %ignore std::vector::vector(size_type); %ignore std::vector::resize(size_type); #endif +#if defined(SWIGJAVA) +#define SWIG_GOOD_VECTOR +%ignore std::vector::vector(jint); +%ignore std::vector::resize(jint); +#endif + #if defined(SWIGTCL) || defined(SWIGPERL) #define SWIG_GOOD_VECTOR /* here, for languages with bad declaration */ diff --git a/Examples/test-suite/import_fragments.i b/Examples/test-suite/import_fragments.i new file mode 100644 index 000000000..26b87cdb2 --- /dev/null +++ b/Examples/test-suite/import_fragments.i @@ -0,0 +1,18 @@ +%module import_fragments + +// Check %fragments forced inclusion does not result in code generation when using %import +%import "import_fragments_a.i" + +%{ +template +struct TemplateA4 {}; +%} + +%template(TemplateA4Int) TemplateA4; + +%inline %{ +int getImport4() { + // Requires the ImportA4 fragment to be generated in order to compile + return ImportA4; +} +%} diff --git a/Examples/test-suite/import_fragments_a.i b/Examples/test-suite/import_fragments_a.i new file mode 100644 index 000000000..1babea95f --- /dev/null +++ b/Examples/test-suite/import_fragments_a.i @@ -0,0 +1,48 @@ +#if !defined(SWIGGO) +// Prevent Go from generating a Go module import - this test is not set up as true multiple modules +%module import_fragments_a +#endif + +%fragment("ImportA1", "header") %{ +ImportA1_this_will_not_compile; +%} +%fragment("ImportA2", "header") %{ +ImportA2_this_will_not_compile; +%} +%fragment("ImportA3", "header") %{ +ImportA3_this_will_not_compile; +%} +%fragment("ImportA4", "header") %{ +static int ImportA4 = 99; +%} +%fragment("ImportA5", "header") %{ +ImportA5_this_will_not_compile; +%} + +%fragment("ImportA1"); + +%{ +Import_will_not_compile; +%} + +struct StructA { + %fragment("ImportA2"); +}; + +template +struct TemplateA3 { + %fragment("ImportA3"); +}; + +template +struct TemplateA4 { + %fragment("ImportA4"); +}; + +template +struct TemplateA5 { + %fragment("ImportA5"); +}; +%template(TemplateA5Double) TemplateA5; + +%include "import_fragments_b.i" diff --git a/Examples/test-suite/import_fragments_b.i b/Examples/test-suite/import_fragments_b.i new file mode 100644 index 000000000..615db4796 --- /dev/null +++ b/Examples/test-suite/import_fragments_b.i @@ -0,0 +1,9 @@ +%module import_fragments_b + +%fragment("ImportB", "header") %{ +ImportB_this_will_not_compile; +%} + +%fragment("ImportB"); + + diff --git a/Examples/test-suite/imports_a.h b/Examples/test-suite/imports_a.h index f761ea38c..f441d340b 100644 --- a/Examples/test-suite/imports_a.h +++ b/Examples/test-suite/imports_a.h @@ -18,4 +18,12 @@ class A { virtual MemberEnum member_virtual_test(MemberEnum e) { return e; } virtual GlobalEnum global_virtual_test(GlobalEnum e) { return global_test(e); } }; + +/* This class overrides nothing. Inherited classes should see base functions. +*/ +class A_Intermediate : public A { + public: + A_Intermediate(){} + ~A_Intermediate(){} +}; #endif diff --git a/Examples/test-suite/imports_b.h b/Examples/test-suite/imports_b.h index f50cee576..328dac273 100644 --- a/Examples/test-suite/imports_b.h +++ b/Examples/test-suite/imports_b.h @@ -1,6 +1,6 @@ #include "imports_a.h" -class B : public A +class B : public A_Intermediate { public: B() {}; diff --git a/Examples/test-suite/insert_directive.h b/Examples/test-suite/insert_directive.h new file mode 100644 index 000000000..2187ff5b3 --- /dev/null +++ b/Examples/test-suite/insert_directive.h @@ -0,0 +1,2 @@ +// %inserted code %header from file +int inserted_header4(int i) { return inserted_header3(i); } diff --git a/Examples/test-suite/insert_directive.i b/Examples/test-suite/insert_directive.i index 36c3af6c6..3cff40bbf 100644 --- a/Examples/test-suite/insert_directive.i +++ b/Examples/test-suite/insert_directive.i @@ -27,9 +27,11 @@ int inserted_header2(int i) { return inserted_header1(i); } int inserted_header3(int i) { return inserted_header2(i); } %} +%header "insert_directive.h" + %wrapper %{ // %inserted code %wrapper -int inserted_wrapper(int i) { return inserted_header3(i); } +int inserted_wrapper(int i) { return inserted_header4(i); } %} %init %{ diff --git a/Examples/test-suite/intermediary_classname.i b/Examples/test-suite/intermediary_classname.i index 94858a5fb..585967ad4 100644 --- a/Examples/test-suite/intermediary_classname.i +++ b/Examples/test-suite/intermediary_classname.i @@ -4,6 +4,12 @@ %warnfilter(SWIGWARN_TYPEMAP_THREAD_UNSAFE,SWIGWARN_TYPEMAP_DIRECTOROUT_PTR); +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW2(T1, T2) throw(T1, T2) +%{ +#define TESTCASE_THROW2(T1, T2) +%} + // change the access to the intermediary class for testing purposes %pragma(java) jniclassclassmodifiers="public class"; %pragma(csharp) imclassclassmodifiers="public class"; @@ -41,10 +47,6 @@ template class vector { void testconst(const T x) { } }; -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - class Base { public: Base() : mVectInt(0) {} @@ -65,11 +67,8 @@ public: virtual Base& m1(Base &b) { return b; } virtual Base* m2(Base *b) { return b; } // virtual Base m3(Base b) { return b; } - void throwspec() throw (int, Base) {} + void throwspec() TESTCASE_THROW2(int, Base) {} }; -#if defined(_MSC_VER) - #pragma warning(default: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif %} %template(maxint) maximum; diff --git a/Examples/test-suite/java/CommentParser.java b/Examples/test-suite/java/CommentParser.java new file mode 100644 index 000000000..7dc6d591d --- /dev/null +++ b/Examples/test-suite/java/CommentParser.java @@ -0,0 +1,172 @@ + +import com.sun.javadoc.*; +import java.util.HashMap; +import java.util.Map.Entry; +import java.util.Map; +import java.util.Set; +import java.util.Iterator; +import java.io.BufferedWriter; +import java.io.OutputStreamWriter; +import java.io.FileOutputStream; +import java.io.IOException; + + +public class CommentParser { + private static Map m_parsedComments = new HashMap(); + + public static boolean start(RootDoc root) { + + /* + * This method is called by 'javadoc' and gets the whole parsed java + * file, we get comments and store them + */ + + for (ClassDoc classDoc : root.classes()) { + + if (classDoc.getRawCommentText().length() > 0) + m_parsedComments.put(classDoc.qualifiedName(), classDoc.getRawCommentText()); + + for (FieldDoc f : classDoc.enumConstants()) { + if (f.getRawCommentText().length() > 0) + m_parsedComments.put(f.qualifiedName(), f.getRawCommentText()); + } + for (FieldDoc f : classDoc.fields()) { + if (f.getRawCommentText().length() > 0) + m_parsedComments.put(f.qualifiedName(), f.getRawCommentText()); + } + for (ConstructorDoc c : classDoc.constructors()) { + if (c.getRawCommentText().length() > 0) + m_parsedComments.put(c.toString(), c.getRawCommentText()); + } + for (MethodDoc m : classDoc.methods()) { + if (m.getRawCommentText().length() > 0) + m_parsedComments.put(m.toString(), m.getRawCommentText()); + } + } + return true; + } + + + public int check(Map wantedComments) { + int errorCount=0; + Iterator> it = m_parsedComments.entrySet().iterator(); + + while (it.hasNext()) { + + Entry e = (Entry) it.next(); + String actualStr = e.getValue(); + String wantedStr = wantedComments.get(e.getKey()); + // this may be weird, but I don't know any more effective solution + actualStr = actualStr.replace(" ", ""); + actualStr = actualStr.replaceAll("\t", ""); + actualStr = actualStr.replace("\n", ""); + + // Removing of
    is temporary solution, since adding of + //
    tag requires changes in all tests. However,
    + // tag should be added more selectively and when this is + // implemented, tests should be updated. + actualStr = actualStr.replace("
    ", ""); + + if (wantedStr != null) { + wantedStr = wantedStr.replace(" ", ""); + wantedStr = wantedStr.replace("\t", ""); + wantedStr = wantedStr.replace("\n", ""); + wantedStr = wantedStr.replace("
    ", ""); + } + /* The following lines replace multiple whitespaces with a single one. + Although this would be more exact testing, it would also require + more work on test maintenance. + actualStr = actualStr.replace('\t', ' '); + actualStr = actualStr.replaceAll(" +", " "); + // actualStr = actualStr.replace("\n", ""); + if (wantedStr != null) { + wantedStr = wantedStr.replace('\t', ' '); + wantedStr = wantedStr.replaceAll(" +", " "); + // wantedStr = wantedStr.replace("\n", ""); + } */ + + if (!actualStr.equals(wantedStr)) { + System.out.println("\n\n////////////////////////////////////////////////////////////////////////"); + System.out.println("Documentation comments for '" + e.getKey() + "' do not match!"); + String expectedFileName = "expected.txt"; + String gotFileName = "got.txt"; + System.out.println("Output is also saved to files '" + expectedFileName + + "' and '" + gotFileName + "'"); + // here we print original strings, for nicer output + System.out.println("\n\n---\nexpected:\n" + wantedComments.get(e.getKey())); + System.out.println("\n\n---\ngot:\n" + e.getValue()); + + try { + // write expected string to file + BufferedWriter expectedFile = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(expectedFileName))); + expectedFile.write(wantedComments.get(e.getKey())); + expectedFile.close(); + + // write translated string to file + BufferedWriter gotFile = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(gotFileName))); + gotFile.write(e.getValue().replace("
    ", "")); + gotFile.close(); + } catch (IOException ex) { + System.out.println("Error when writing output to file: " + ex); + } + + errorCount++; + } + } + + if (m_parsedComments.size() != wantedComments.size()) { + System.out.println("Mismatch in the number of comments!\n Expected: " + + wantedComments.size() + "\n Parsed: " + + m_parsedComments.size()); + System.out.println("Expected keys: "); + printKeys(wantedComments); + System.out.println("Parsed keys: "); + printKeys(m_parsedComments); + + errorCount++; + } + + return errorCount > 0 ? 1 : 0; + } + + + private void printKeys(Map map) { + + Set keys = map.keySet(); + for (String key : keys) { + System.out.println(" " + key); + } + } + + + public static void printCommentListForJavaSource() { + + Iterator< Entry > it = m_parsedComments.entrySet().iterator(); + + while (it.hasNext()) { + + Entry e = (Entry) it.next(); + String commentText = e.getValue(); + commentText = commentText.replace("\\", "\\\\"); + commentText = commentText.replace("\"", "\\\""); + commentText = commentText.replace("\n", "\\n\" +\n\t\t\""); + System.out.format("wantedComments.put(\"%s\",\n\t\t\"%s\");\n", e.getKey(), commentText); + } + } + + + public static void main(String argv[]) { + + if (argv.length<1) { + System.out.format("Usage:\n\tCommentParser \n"); + System.exit(1); + } + + com.sun.tools.javadoc.Main.execute("The comment parser program", + "CommentParser", new String[]{"-quiet", argv[0]}); + + // if we are run as standalone app, print the list of found comments as it would appear in java source + + printCommentListForJavaSource(); + } +} diff --git a/Examples/test-suite/java/Makefile.in b/Examples/test-suite/java/Makefile.in index e69964352..2e788fa07 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -6,6 +6,8 @@ LANGUAGE = java JAVA = @JAVA@ JAVAC = @JAVAC@ JAVAFLAGS = @JAVAFLAGS@ +JAVA_CLASSPATH_SEP = @JAVA_CLASSPATH_SEP@ +JAVA_TOOLS_JAR = @JAVA_TOOLS_JAR@ SCRIPTSUFFIX = _runme.java srcdir = @srcdir@ @@ -28,6 +30,8 @@ CPP_TEST_CASES = \ java_director_exception_feature \ java_director_exception_feature_nspace \ java_director_ptrclass \ + java_director_typemaps \ + java_director_typemaps_ptr \ java_enums \ java_jnitypes \ java_lib_arrays_dimensionless \ @@ -39,11 +43,26 @@ CPP_TEST_CASES = \ java_throws \ java_typemaps_proxy \ java_typemaps_typewrapper \ + li_std_list \ + li_std_map \ + li_std_set \ # li_boost_intrusive_ptr CPP11_TEST_CASES = \ + cpp11_shared_ptr_const \ + cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ + cpp11_shared_ptr_upcast \ + cpp11_std_unordered_map \ + cpp11_std_unordered_set \ cpp11_strongly_typed_enumerations_simple \ +DOXYGEN_TEST_CASES := \ + doxygen_parsing_enums_simple \ + doxygen_parsing_enums_proper \ + doxygen_parsing_enums_typesafe \ + doxygen_parsing_enums_typeunsafe \ + include $(srcdir)/../common.mk # Overridden variables here @@ -53,6 +72,7 @@ JAVA_PACKAGEOPT = -package $(JAVA_PACKAGE) SWIGOPT += $(JAVA_PACKAGEOPT) # Custom tests - tests with additional commandline options +cpp17_nspace_nested_namespaces.%: JAVA_PACKAGE = $*Package director_nspace.%: JAVA_PACKAGE = $*Package director_nspace_director_name_collision.%: JAVA_PACKAGE = $*Package java_director_exception_feature_nspace.%: JAVA_PACKAGE = $*Package @@ -88,14 +108,23 @@ setup = \ mkdir $(JAVA_PACKAGE); \ fi +# Doxygen test cases need to be compiled together with the CommentParser class +# which depends on com.sun.javadoc package which is located in this JAR. +CommentParser.class: + $(COMPILETOOL) $(JAVAC) -classpath $(JAVA_CLASSPATH) -d . $(srcdir)/CommentParser.java + +JAVA_CLASSPATH := . +$(DOXYGEN_TEST_CASES:=.cpptest): JAVA_CLASSPATH := "$(JAVA_TOOLS_JAR)$(JAVA_CLASSPATH_SEP)." +$(DOXYGEN_TEST_CASES:=.cpptest): CommentParser.class + # Compiles java files then runs the testcase. A testcase is only run if # a file is found which has _runme.java appended after the testcase name. # Note Java uses LD_LIBRARY_PATH under Unix, PATH under Cygwin/Windows, SHLIB_PATH on HPUX and DYLD_LIBRARY_PATH on Mac OS X. run_testcase = \ cd $(JAVA_PACKAGE) && $(COMPILETOOL) $(JAVAC) -classpath . `find . -name "*.java"` && cd .. && \ if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ - $(COMPILETOOL) $(JAVAC) -classpath . -d . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ - env LD_LIBRARY_PATH="$(JAVA_PACKAGE):$$LD_LIBRARY_PATH" PATH="$(JAVA_PACKAGE):$$PATH" SHLIB_PATH="$(JAVA_PACKAGE):$$SHLIB_PATH" DYLD_LIBRARY_PATH="$(JAVA_PACKAGE):$$DYLD_LIBRARY_PATH" $(RUNTOOL) $(JAVA) $(JAVAFLAGS) -classpath . $*_runme; \ + $(COMPILETOOL) $(JAVAC) -classpath $(JAVA_CLASSPATH) -d . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ + env LD_LIBRARY_PATH="$(JAVA_PACKAGE):$$LD_LIBRARY_PATH" PATH="$(JAVA_PACKAGE):$$PATH" SHLIB_PATH="$(JAVA_PACKAGE):$$SHLIB_PATH" DYLD_LIBRARY_PATH="$(JAVA_PACKAGE):$$DYLD_LIBRARY_PATH" $(RUNTOOL) $(JAVA) $(JAVAFLAGS) -classpath $(JAVA_CLASSPATH) $*_runme; \ fi # Clean: remove testcase directories diff --git a/Examples/test-suite/java/class_scope_namespace_runme.java b/Examples/test-suite/java/class_scope_namespace_runme.java new file mode 100644 index 000000000..e55393e2b --- /dev/null +++ b/Examples/test-suite/java/class_scope_namespace_runme.java @@ -0,0 +1,59 @@ + +import class_scope_namespace.*; + +public class class_scope_namespace_runme { + + static { + try { + System.loadLibrary("class_scope_namespace"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + A a = new A(); + B b = new B(); + C c = new C(); + D d = new D(); + E e = new E(); + F f = new F(); + G g = new G(); + H.HH h = new H.HH(); + I_.II i = new I_.II(); + J j = new J(); + K k = new K(); + L l = new L(); + M m = new M(); + + a.aa(a, a, a); + b.bb(b, b); + c.cc(c, c); + d.dd(d, d, d); + e.ee(e, e, e); + f.ff(f, f, f, f); + g.gg(g, g); + h.hh(h); + i.ii(i, i); + j.jj(j, j, j); + k.kk(k, k, k); + l.ll(l, l, l); + m.mm(m, m, m); + + class_scope_namespace.aaa(a, a, a); + class_scope_namespace.bbb(b, b); + class_scope_namespace.ccc(c, c); + class_scope_namespace.ddd(d, d, d); + class_scope_namespace.eee(e, e, e); + class_scope_namespace.fff(f, f, f, f); + class_scope_namespace.ggg(g, g); + class_scope_namespace.hhh(h); + class_scope_namespace.iii(i, i); + class_scope_namespace.jjj(j, j, j); + class_scope_namespace.kkk(k, k, k); + class_scope_namespace.lll(l, l, l); + class_scope_namespace.mmm(m, m, m); + } +} diff --git a/Examples/test-suite/java/cpp11_alias_nested_template_scoping_runme.java b/Examples/test-suite/java/cpp11_alias_nested_template_scoping_runme.java new file mode 100644 index 000000000..7afa83a0f --- /dev/null +++ b/Examples/test-suite/java/cpp11_alias_nested_template_scoping_runme.java @@ -0,0 +1,32 @@ + +import cpp11_alias_nested_template_scoping.*; + +public class cpp11_alias_nested_template_scoping_runme { + + static { + try { + System.loadLibrary("cpp11_alias_nested_template_scoping"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + Yshort ys = new Yshort(); + short val = 0; + val = ys.create1(); + val = ys.create2(); + val = ys.create3(); + val = ys.create4(); + val = ys.create5(); + val = ys.create6(); + val = ys.create7(); + + val = ys.create13(); + + val = ys.create15(); + val = ys.create16(); + val = ys.create17(); + } +} diff --git a/Examples/test-suite/java/cpp11_initializer_list_runme.java b/Examples/test-suite/java/cpp11_initializer_list_runme.java new file mode 100644 index 000000000..0318c9e90 --- /dev/null +++ b/Examples/test-suite/java/cpp11_initializer_list_runme.java @@ -0,0 +1,21 @@ + +import cpp11_initializer_list.*; + +public class cpp11_initializer_list_runme { + + static { + try { + System.loadLibrary("cpp11_initializer_list"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + C c = new C(null); + String joined = c.get_joined_string(); + if (!joined.equals("AbFab")) + throw new RuntimeException("Wrong joined string " + joined); + } +} diff --git a/Examples/test-suite/java/cpp11_raw_string_literals_runme.java b/Examples/test-suite/java/cpp11_raw_string_literals_runme.java new file mode 100644 index 000000000..396c0ba06 --- /dev/null +++ b/Examples/test-suite/java/cpp11_raw_string_literals_runme.java @@ -0,0 +1,67 @@ +import cpp11_raw_string_literals.*; + +public class cpp11_raw_string_literals_runme { + + static { + try { + System.loadLibrary("cpp11_raw_string_literals"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + if (cpp11_raw_string_literals.getL() != 100) + throw new RuntimeException("failed!"); + + if (cpp11_raw_string_literals.getU8() != 100) + throw new RuntimeException("failed!"); + + if (cpp11_raw_string_literals.getU() != 100) + throw new RuntimeException("failed!"); + + if (UStruct.U != 100) + throw new RuntimeException("failed!"); + + + if (cpp11_raw_string_literals.getR() != 100) + throw new RuntimeException("failed!"); + + if (cpp11_raw_string_literals.getLR() != 100) + throw new RuntimeException("failed!"); + + if (cpp11_raw_string_literals.getU8R() != 100) + throw new RuntimeException("failed!"); + + if (cpp11_raw_string_literals.getUR() != 100) + throw new RuntimeException("failed!"); + + if (URStruct.UR != 100) + throw new RuntimeException("failed!"); + + + if (!cpp11_raw_string_literals.getAa().equals("Wide string")) + throw new RuntimeException("failed!"); + + if (!cpp11_raw_string_literals.getBb().equals("UTF-8 string")) + throw new RuntimeException("failed!"); + + if (!cpp11_raw_string_literals.getXx().equals(")I'm an \"ascii\" \\ string.")) + throw new RuntimeException("failed!"); + + if (!cpp11_raw_string_literals.getEe().equals(")I'm an \"ascii\" \\ string.")) + throw new RuntimeException("failed!"); + + if (!cpp11_raw_string_literals.getFf().equals("I'm a \"raw wide\" \\ string.")) + throw new RuntimeException("failed!"); + + if (!cpp11_raw_string_literals.getGg().equals("I'm a \"raw UTF-8\" \\ string.")) + throw new RuntimeException("failed!"); + + + + if (!cpp11_raw_string_literalsConstants.mm.equals(")I'm an \"ascii\" \\ string constant with multiple\n\nlines.")) + throw new RuntimeException("failed!"); + } +} diff --git a/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java b/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java new file mode 100644 index 000000000..4755f8d1f --- /dev/null +++ b/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java @@ -0,0 +1,56 @@ + +import cpp11_ref_qualifiers.*; + +public class cpp11_ref_qualifiers_runme { + + static { + try { + System.loadLibrary("cpp11_ref_qualifiers"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + Host h = new Host(); + + // Basic testing + h.h1(); + h.h2(); + h.h6(); + h.h7(); + + h.h(); + + // %feature testing + Features f = new Features(); + if (!f.F1().equals("F1")) throw new RuntimeException("Fail"); + if (!f.F2().equals("F2")) throw new RuntimeException("Fail"); + if (!f.F3().equals("F3")) throw new RuntimeException("Fail"); + + if (!f.C1(0).equals("C1")) throw new RuntimeException("Fail"); + if (!f.C2(0).equals("C2")) throw new RuntimeException("Fail"); + if (!f.C3(0).equals("C3")) throw new RuntimeException("Fail"); + + // %rename testing + Renames r = new Renames(); + r.RR1(); + r.RR2(); + r.RR3(); + + r.SS1(0); + r.SS2(0); + r.SS3(0); + + // Conversion operators + String s = null; + ConversionOperators co = new ConversionOperators(); + s = co.StringConvertCopy(); + s = co.StringConvertMove(); + + ConversionOperators2 co2 = new ConversionOperators2(); + s = co2.StringConvertMove(); + } +} + diff --git a/Examples/test-suite/java/cpp11_ref_qualifiers_rvalue_unignore_runme.java b/Examples/test-suite/java/cpp11_ref_qualifiers_rvalue_unignore_runme.java new file mode 100644 index 000000000..bbbe6f788 --- /dev/null +++ b/Examples/test-suite/java/cpp11_ref_qualifiers_rvalue_unignore_runme.java @@ -0,0 +1,20 @@ + +import cpp11_ref_qualifiers_rvalue_unignore.*; + +public class cpp11_ref_qualifiers_rvalue_unignore_runme { + + static { + try { + System.loadLibrary("cpp11_ref_qualifiers_rvalue_unignore"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + new RefQualifier().m1(); + new RefQualifier().m2(); + } +} + diff --git a/Examples/test-suite/java/cpp11_ref_qualifiers_typemaps_runme.java b/Examples/test-suite/java/cpp11_ref_qualifiers_typemaps_runme.java new file mode 100644 index 000000000..8c6a21b15 --- /dev/null +++ b/Examples/test-suite/java/cpp11_ref_qualifiers_typemaps_runme.java @@ -0,0 +1,39 @@ +import cpp11_ref_qualifiers_typemaps.*; + +public class cpp11_ref_qualifiers_typemaps_runme { + static { + try { + System.loadLibrary("cpp11_ref_qualifiers_typemaps"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + { + TypemapsNamedParms tm = new TypemapsNamedParms(); + if (tm.fff(cpp11_ref_qualifiers_typemaps.FF1_MFP) != 2) + throw new RuntimeException("failed"); + if (tm.ccc(cpp11_ref_qualifiers_typemaps.CC4_MFP) != 5) + throw new RuntimeException("failed"); + if (tm.ggg(cpp11_ref_qualifiers_typemaps.GG7_MFP) != 8) + throw new RuntimeException("failed"); + if (tm.hhh(cpp11_ref_qualifiers_typemaps.HH10_MFP) != 11) + throw new RuntimeException("failed"); + } + { + TypemapsUnnamedParms tm = new TypemapsUnnamedParms(); + if (tm.fff(cpp11_ref_qualifiers_typemaps.FF1_MFP) != 3) + throw new RuntimeException("failed"); + if (tm.ccc(cpp11_ref_qualifiers_typemaps.CC4_MFP) != 6) + throw new RuntimeException("failed"); + if (tm.ggg(cpp11_ref_qualifiers_typemaps.GG7_MFP) != 9) + throw new RuntimeException("failed"); + if (tm.hhh(cpp11_ref_qualifiers_typemaps.HH10_MFP) != 12) + throw new RuntimeException("failed"); + } + } +} + diff --git a/Examples/test-suite/java/cpp11_shared_ptr_overload_runme.java b/Examples/test-suite/java/cpp11_shared_ptr_overload_runme.java new file mode 100644 index 000000000..27dfe1830 --- /dev/null +++ b/Examples/test-suite/java/cpp11_shared_ptr_overload_runme.java @@ -0,0 +1,60 @@ +import cpp11_shared_ptr_overload.*; + +public class cpp11_shared_ptr_overload_runme { + static { + try { + System.loadLibrary("cpp11_shared_ptr_overload"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + String ret = null; + + // ref + ret = cpp11_shared_ptr_overload.UseA(new MyType("123")); + if (!ret.equals("123 ref")) throw new RuntimeException("UseA fail:" + ret); + + ret = cpp11_shared_ptr_overload.UseB(0, new MyType("123")); + if (!ret.equals("123 ref")) throw new RuntimeException("UseB fail:" + ret); + + ret = cpp11_shared_ptr_overload.UseC(0, new MyType("123"), new MyType("456")); + if (!ret.equals("123 ref")) throw new RuntimeException("UseC fail:" + ret); + + // sharedptr + ret = cpp11_shared_ptr_overload.UseX(new MyType("123")); + if (!ret.equals("123 sharedptr")) throw new RuntimeException("UseX fail:" + ret); + + ret = cpp11_shared_ptr_overload.UseY(0, new MyType("123")); + if (!ret.equals("123 sharedptr")) throw new RuntimeException("UseY fail:" + ret); + + ret = cpp11_shared_ptr_overload.UseZ(0, new MyType("123"), new MyType("456")); + if (!ret.equals("123 sharedptr")) throw new RuntimeException("UseZ fail:" + ret); + + // Combo1-4 + ret = cpp11_shared_ptr_overload.Combo1(new MyType("XXX")); + if (!ret.equals("XXXCombo1")) throw new RuntimeException("Combo1 fail:" + ret); + + ret = cpp11_shared_ptr_overload.Combo2(new MyType("XXX")); + if (!ret.equals("XXXCombo2")) throw new RuntimeException("Combo2 fail:" + ret); + + ret = cpp11_shared_ptr_overload.Combo3(new MyType("XXX")); + if (!ret.equals("XXXCombo3")) throw new RuntimeException("Combo3 fail:" + ret); + + ret = cpp11_shared_ptr_overload.Combo4(new MyType("XXX")); + if (!ret.equals("XXXCombo4")) throw new RuntimeException("Combo4 fail:" + ret); + + // Combo5-7 + ret = cpp11_shared_ptr_overload.Combo5(new MyType("XXX")); + if (!ret.equals("XXXCombo5")) throw new RuntimeException("Combo5 fail:" + ret); + + ret = cpp11_shared_ptr_overload.Combo6(new MyType("XXX")); + if (!ret.equals("XXXCombo6")) throw new RuntimeException("Combo6 fail:" + ret); + + ret = cpp11_shared_ptr_overload.Combo7(new MyType("XXX")); + if (!ret.equals("XXXCombo7")) throw new RuntimeException("Combo7 fail:" + ret); + } +} diff --git a/Examples/test-suite/java/cpp11_li_std_array_runme.java b/Examples/test-suite/java/cpp11_std_array_runme.java similarity index 75% rename from Examples/test-suite/java/cpp11_li_std_array_runme.java rename to Examples/test-suite/java/cpp11_std_array_runme.java index 2e2a20138..58fdc176b 100644 --- a/Examples/test-suite/java/cpp11_li_std_array_runme.java +++ b/Examples/test-suite/java/cpp11_std_array_runme.java @@ -1,10 +1,10 @@ -import cpp11_li_std_array.*; +import cpp11_std_array.*; -public class cpp11_li_std_array_runme { +public class cpp11_std_array_runme { static { try { - System.loadLibrary("cpp11_li_std_array"); + System.loadLibrary("cpp11_std_array"); } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); System.exit(1); @@ -43,24 +43,24 @@ public class cpp11_li_std_array_runme { compareContainers(ai, vals); // Check return - compareContainers(cpp11_li_std_array.arrayOutVal(), new int[] {-2, -1, 0, 0, 1, 2}); - compareContainers(cpp11_li_std_array.arrayOutConstRef(), new int[] {-2, -1, 0, 0, 1, 2}); - compareContainers(cpp11_li_std_array.arrayOutRef(), new int[] {-2, -1, 0, 0, 1, 2}); - compareContainers(cpp11_li_std_array.arrayOutPtr(), new int[] {-2, -1, 0, 0, 1, 2}); + compareContainers(cpp11_std_array.arrayOutVal(), new int[] {-2, -1, 0, 0, 1, 2}); + compareContainers(cpp11_std_array.arrayOutConstRef(), new int[] {-2, -1, 0, 0, 1, 2}); + compareContainers(cpp11_std_array.arrayOutRef(), new int[] {-2, -1, 0, 0, 1, 2}); + compareContainers(cpp11_std_array.arrayOutPtr(), new int[] {-2, -1, 0, 0, 1, 2}); // Check passing arguments - ai = cpp11_li_std_array.arrayInVal(ToArray6(new int[] {9, 8, 7, 6, 5, 4})); + ai = cpp11_std_array.arrayInVal(ToArray6(new int[] {9, 8, 7, 6, 5, 4})); compareContainers(ai, new int[] {90, 80, 70, 60, 50, 40}); - ai = cpp11_li_std_array.arrayInConstRef(ToArray6(new int[] {9, 8, 7, 6, 5, 4})); + ai = cpp11_std_array.arrayInConstRef(ToArray6(new int[] {9, 8, 7, 6, 5, 4})); compareContainers(ai, new int[] {90, 80, 70, 60, 50, 40}); ai = new ArrayInt6(ToArray6(new int[] {9, 8, 7, 6, 5, 4})); - cpp11_li_std_array.arrayInRef(ai); + cpp11_std_array.arrayInRef(ai); compareContainers(ai, new int[] {90, 80, 70, 60, 50, 40}); ai = new ArrayInt6(ToArray6(new int[] {9, 8, 7, 6, 5, 4})); - cpp11_li_std_array.arrayInPtr(ai); + cpp11_std_array.arrayInPtr(ai); compareContainers(ai, new int[] {90, 80, 70, 60, 50, 40}); // fill diff --git a/Examples/test-suite/java/cpp11_std_unordered_map_runme.java b/Examples/test-suite/java/cpp11_std_unordered_map_runme.java new file mode 100644 index 000000000..79f683378 --- /dev/null +++ b/Examples/test-suite/java/cpp11_std_unordered_map_runme.java @@ -0,0 +1,122 @@ +import cpp11_std_unordered_map.*; + +public class cpp11_std_unordered_map_runme { + + static { + try { + System.loadLibrary("cpp11_std_unordered_map"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void checkThat(boolean mustBeTrue) throws Throwable { + if (!mustBeTrue) { + // Index [2], since this function is one hop away from main, and [1] is the current method. + throw new RuntimeException("Test failed at line number " + Thread.currentThread().getStackTrace()[2].getLineNumber()); + } + } + + public static void main(String argv[]) throws Throwable + { + java.util.AbstractMap sim = new UnorderedMapStringInt(); + java.util.AbstractMap iim = new UnorderedMapIntInt(); + + checkThat(sim.isEmpty()); + checkThat(iim.isEmpty()); + checkThat(sim.size() == 0); + checkThat(iim.size() == 0); + + checkThat(sim.get("key") == null); + checkThat(iim.get(1) == null); + + checkThat(!sim.containsKey("key")); + checkThat(!iim.containsKey(1)); + + checkThat(sim.put("key", 2) == null); + checkThat(iim.put(1, 2) == null); + + checkThat(sim.size() == 1); + checkThat(iim.size() == 1); + checkThat(!sim.isEmpty()); + checkThat(!iim.isEmpty()); + + checkThat(sim.get("key") == 2); + checkThat(iim.get(1) == 2); + + checkThat(sim.remove("key") == 2); + checkThat(iim.remove(1) == 2); + + checkThat(sim.isEmpty()); + checkThat(iim.isEmpty()); + checkThat(sim.size() == 0); + checkThat(iim.size() == 0); + + checkThat(sim.get("key") == null); + checkThat(iim.get(1) == null); + + checkThat(sim.remove("key") == null); + checkThat(iim.remove(1) == null); + + checkThat(sim.put("key", 2) == null); + checkThat(iim.put(1, 2) == null); + + sim.clear(); + iim.clear(); + checkThat(sim.isEmpty()); + checkThat(iim.isEmpty()); + + checkThat(sim.put("key1", 1) == null); + checkThat(iim.put(1, 1) == null); + checkThat(sim.put("key2", 2) == null); + checkThat(iim.put(2, 2) == null); + + checkThat(sim.size() == 2); + checkThat(iim.size() == 2); + checkThat(sim.get("key1") == 1); + checkThat(iim.get(1) == 1); + checkThat(sim.get("key2") == 2); + checkThat(iim.get(2) == 2); + + checkThat(sim.put("key1", 3) == 1); + checkThat(iim.put(1, 3) == 1); + + checkThat(sim.size() == 2); + checkThat(iim.size() == 2); + checkThat(sim.get("key1") == 3); + checkThat(iim.get(1) == 3); + + java.util.Set> sim_es = sim.entrySet(); + java.util.Map sim_default = new java.util.HashMap(); + sim_default.put("key1", 3); + sim_default.put("key2", 2); + java.util.Set> sim_es_default = sim_default.entrySet(); + checkThat(sim_es.size() == sim_es_default.size()); + for (java.util.Map.Entry entry : sim_es) { + checkThat(sim_es_default.contains(entry)); + checkThat(sim_default.containsKey(entry.getKey())); + checkThat(sim_default.containsValue(entry.getValue())); + + Integer oldValue = entry.getValue(); + entry.setValue(oldValue + 1); + checkThat(sim.get(entry.getKey()) == (oldValue + 1)); + } + + java.util.Set> iim_es = iim.entrySet(); + java.util.Map iim_default = new java.util.HashMap(); + iim_default.put(1, 3); + iim_default.put(2, 2); + java.util.Set> iim_es_default = iim_default.entrySet(); + checkThat(iim_es.size() == iim_es_default.size()); + for (java.util.Map.Entry entry : iim_es) { + checkThat(iim_es_default.contains(entry)); + checkThat(iim_default.containsKey(entry.getKey())); + checkThat(iim_default.containsValue(entry.getValue())); + + Integer oldValue = entry.getValue(); + entry.setValue(oldValue + 1); + checkThat(iim.get(entry.getKey()) == (oldValue + 1)); + } + } +} diff --git a/Examples/test-suite/java/cpp11_std_unordered_set_runme.java b/Examples/test-suite/java/cpp11_std_unordered_set_runme.java new file mode 100644 index 000000000..9d64ab240 --- /dev/null +++ b/Examples/test-suite/java/cpp11_std_unordered_set_runme.java @@ -0,0 +1,75 @@ +import cpp11_std_unordered_set.*; + +public class cpp11_std_unordered_set_runme { + + static { + try { + System.loadLibrary("cpp11_std_unordered_set"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void checkThat(boolean mustBeTrue) throws Throwable { + if (!mustBeTrue) { + // Index [2], since this function is one hop away from main, and [1] is the current method. + throw new RuntimeException("Test failed at line number " + Thread.currentThread().getStackTrace()[2].getLineNumber()); + } + } + + public static void main(String argv[]) throws Throwable + { + java.util.AbstractSet ss = new UnorderedSetString(); + + checkThat(ss.isEmpty()); + checkThat(!ss.contains("key")); + checkThat(!ss.remove("key")); + + checkThat(ss.add("key")); + checkThat(!ss.add("key")); + checkThat(ss.contains("key")); + checkThat(ss.remove("key")); + checkThat(ss.isEmpty()); + checkThat(ss.size() == 0); + + checkThat(ss.add("key1")); + checkThat(ss.add("key2")); + checkThat(ss.add("key3")); + checkThat(ss.size() == 3); + + ss.clear(); + checkThat(ss.isEmpty()); + checkThat(ss.size() == 0); + + checkThat(ss.addAll(java.util.Arrays.asList("one", "two", "three"))); + checkThat(ss.size() == 3); + checkThat(ss.contains("one")); + checkThat(!ss.contains("four")); + + checkThat(ss.containsAll(java.util.Arrays.asList("one", "two", "three"))); + checkThat(ss.containsAll(java.util.Arrays.asList("one", "two"))); + checkThat(!ss.containsAll(java.util.Arrays.asList("one", "two", "four"))); + checkThat(!ss.containsAll(java.util.Arrays.asList("one", "two", "three", "four"))); + + checkThat(!ss.addAll(java.util.Arrays.asList("one", "two", "three"))); + + java.util.Set found = new java.util.HashSet(); + java.util.Iterator itr = ss.iterator(); + while (itr.hasNext()) { + found.add(itr.next()); + } + + checkThat(ss.containsAll(found)); + checkThat(found.containsAll(ss)); + + java.util.AbstractSet ss2 = new UnorderedSetString(ss); + checkThat(ss2.containsAll(ss)); + checkThat(ss.containsAll(ss2)); + + checkThat(!ss.removeAll(java.util.Arrays.asList("five", "four"))); + checkThat(ss.removeAll(found)); + checkThat(ss.isEmpty()); + checkThat(ss.size() == 0); + } +} diff --git a/Examples/test-suite/java/cpp11_template_typedefs_runme.java b/Examples/test-suite/java/cpp11_template_typedefs_runme.java new file mode 100644 index 000000000..473e7cf07 --- /dev/null +++ b/Examples/test-suite/java/cpp11_template_typedefs_runme.java @@ -0,0 +1,19 @@ +import cpp11_template_typedefs.*; + +public class cpp11_template_typedefs_runme { + + static { + try { + System.loadLibrary("cpp11_template_typedefs"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + int alloc1 = cpp11_template_typedefs.get_bucket_allocator1(); + int alloc2 = cpp11_template_typedefs.get_bucket_allocator2(); + } +} + diff --git a/Examples/test-suite/java/cpp17_nested_namespaces_runme.java b/Examples/test-suite/java/cpp17_nested_namespaces_runme.java new file mode 100644 index 000000000..ac29dee19 --- /dev/null +++ b/Examples/test-suite/java/cpp17_nested_namespaces_runme.java @@ -0,0 +1,32 @@ +import cpp17_nested_namespaces.*; + +public class cpp17_nested_namespaces_runme { + + static { + try { + System.loadLibrary("cpp17_nested_namespaces"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + new A1Struct().A1Method(); + new B1Struct().B1Method(); + new C1Struct().C1Method(); + cpp17_nested_namespaces.createA1Struct().A1Method(); + cpp17_nested_namespaces.createB1Struct().B1Method(); + cpp17_nested_namespaces.createC1Struct().C1Method(); + + new B2Struct().B2Method(); + new C2Struct().C2Method(); + cpp17_nested_namespaces.createB2Struct().B2Method(); + cpp17_nested_namespaces.createC2Struct().C2Method(); + + new B3Struct().B3Method(); + new C3Struct().C3Method(); + cpp17_nested_namespaces.createB3Struct().B3Method(); + cpp17_nested_namespaces.createC3Struct().C3Method(); + } +} diff --git a/Examples/test-suite/java/cpp17_nspace_nested_namespaces_runme.java b/Examples/test-suite/java/cpp17_nspace_nested_namespaces_runme.java new file mode 100644 index 000000000..e603484ab --- /dev/null +++ b/Examples/test-suite/java/cpp17_nspace_nested_namespaces_runme.java @@ -0,0 +1,30 @@ +public class cpp17_nspace_nested_namespaces_runme { + + static { + try { + System.loadLibrary("cpp17_nspace_nested_namespaces"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + new cpp17_nspace_nested_namespacesPackage.A1.A1Struct().A1Method(); + new cpp17_nspace_nested_namespacesPackage.A1.B1.B1Struct().B1Method(); + new cpp17_nspace_nested_namespacesPackage.A1.B1.C1.C1Struct().C1Method(); + cpp17_nspace_nested_namespacesPackage.cpp17_nspace_nested_namespaces.createA1Struct().A1Method(); + cpp17_nspace_nested_namespacesPackage.cpp17_nspace_nested_namespaces.createB1Struct().B1Method(); + cpp17_nspace_nested_namespacesPackage.cpp17_nspace_nested_namespaces.createC1Struct().C1Method(); + + new cpp17_nspace_nested_namespacesPackage.A2.B2.B2Struct().B2Method(); + new cpp17_nspace_nested_namespacesPackage.A2.B2.C2.C2Struct().C2Method(); + cpp17_nspace_nested_namespacesPackage.cpp17_nspace_nested_namespaces.createB2Struct().B2Method(); + cpp17_nspace_nested_namespacesPackage.cpp17_nspace_nested_namespaces.createC2Struct().C2Method(); + + new cpp17_nspace_nested_namespacesPackage.A3.B3.B3Struct().B3Method(); + new cpp17_nspace_nested_namespacesPackage.A3.B3.C3.C3Struct().C3Method(); + cpp17_nspace_nested_namespacesPackage.cpp17_nspace_nested_namespaces.createB3Struct().B3Method(); + cpp17_nspace_nested_namespacesPackage.cpp17_nspace_nested_namespaces.createC3Struct().C3Method(); + } +} diff --git a/Examples/test-suite/java/director_classes_runme.java b/Examples/test-suite/java/director_classes_runme.java index 5fbb9ea35..5992b5dd9 100644 --- a/Examples/test-suite/java/director_classes_runme.java +++ b/Examples/test-suite/java/director_classes_runme.java @@ -16,6 +16,7 @@ Expected output if PrintDebug enabled: Base - Val(444.555) Base - Ref(444.555) Base - Ptr(444.555) +Base - ConstPtrRef(444.555) Base - FullyOverloaded(int 10) Base - FullyOverloaded(bool 1) Base - SemiOverloaded(int -678) @@ -26,6 +27,7 @@ Base - DefaultParms(10, 1.1) Derived - Val(444.555) Derived - Ref(444.555) Derived - Ptr(444.555) +Derived - ConstPtrRef(444.555) Derived - FullyOverloaded(int 10) Derived - FullyOverloaded(bool 1) Derived - SemiOverloaded(int -678) @@ -36,6 +38,7 @@ Derived - DefaultParms(10, 1.1) JavaDerived - Val(444.555) JavaDerived - Ref(444.555) JavaDerived - Ptr(444.555) +JavaDerived - ConstPtrRef(444.555) JavaDerived - FullyOverloaded(int 10) JavaDerived - FullyOverloaded(bool True) JavaDerived - SemiOverloaded(-678) @@ -67,7 +70,7 @@ public class director_classes_runme { void run() { - if (director_classes.getPrintDebug()) System.out.println("------------ Start ------------ "); + if (director_classes.getPrintDebug()) System.out.println("------------ Start ------------"); Caller myCaller = new Caller(); @@ -96,7 +99,7 @@ public class director_classes_runme { myBase.delete(); } - if (director_classes.getPrintDebug()) System.out.println("------------ Finish ------------ "); + if (director_classes.getPrintDebug()) System.out.println("------------ Finish ------------"); } void makeCalls(Caller myCaller, Base myBase) @@ -111,6 +114,7 @@ public class director_classes_runme { if (myCaller.ValCall(dh).getVal() != dh.getVal()) throw new RuntimeException("failed"); if (myCaller.RefCall(dh).getVal() != dh.getVal()) throw new RuntimeException("failed"); if (myCaller.PtrCall(dh).getVal() != dh.getVal()) throw new RuntimeException("failed"); + if (myCaller.ConstPtrRefCall(dh).getVal() != dh.getVal()) throw new RuntimeException("failed"); // Fully overloaded method test (all methods in base class are overloaded) if (!myCaller.FullyOverloadedCall(10).equals(baseSimpleName + "::FullyOverloaded(int)")) { @@ -170,6 +174,11 @@ class JavaDerived extends Base if (director_classes.getPrintDebug()) System.out.println("JavaDerived - Ptr(" + x.getVal() + ")"); return x; } + public DoubleHolder ConstPtrRef(DoubleHolder x) + { + if (director_classes.getPrintDebug()) System.out.println("JavaDerived - ConstPtrRef(" + x.getVal() + ")"); + return x; + } public String FullyOverloaded(int x) { if (director_classes.getPrintDebug()) System.out.println("JavaDerived - FullyOverloaded(int " + x + ")"); diff --git a/Examples/test-suite/java/director_exception_catches_runme.java b/Examples/test-suite/java/director_exception_catches_runme.java new file mode 100644 index 000000000..c6fed192d --- /dev/null +++ b/Examples/test-suite/java/director_exception_catches_runme.java @@ -0,0 +1,35 @@ + +import director_exception_catches.*; + +public class director_exception_catches_runme { + + static { + try { + System.loadLibrary("director_exception_catches"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + + BaseClass b = new director_exception_catches_MyClass(); + + try { + String s = BaseClass.call_description(b); + throw new RuntimeException("Failed to catch exception"); + } catch (NullPointerException e) { + if (!e.getMessage().startsWith("Testing exception thrown in BaseClass.description")) + throw new RuntimeException("Unexpected exception message: " + e.getMessage()); + } + } +} + +class director_exception_catches_MyClass extends BaseClass { + @Override + public String description() { + throw new NullPointerException("Testing exception thrown in BaseClass.description"); + } +} + diff --git a/Examples/test-suite/java/director_ownership_runme.java b/Examples/test-suite/java/director_ownership_runme.java new file mode 100644 index 000000000..c038f56a4 --- /dev/null +++ b/Examples/test-suite/java/director_ownership_runme.java @@ -0,0 +1,42 @@ +import director_ownership.*; + +public class director_ownership_runme { + + static { + try { + System.loadLibrary("director_ownership"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void set_content_and_release(Container container, ContentBase content) { + content.swigReleaseOwnership(); + container.set_content(content); + } + + public static void main(String argv[]) { + + Container container = new Container(); + + // make a content in java (cMemoryOwn true) + ContentBase content_java = new ContentDerived(); + + // make a content in c++ (cMemoryOwn true) + ContentBase content_cpp = director_ownership.make_content(); + + set_content_and_release(container, content_java); + if (!container.get_content().get_name().equals("ContentDerived")) + throw new RuntimeException("did not get ContentDerived"); + + // when swigReleaseOwnership() is called on content_cpp, swig tries a static_cast to director and calls the method + // director->swig_java_change_ownership. The content created in c++ native library is not a director, therefore a + // segfault may occur. + // With a check done using dynamic_cast this issue could be avoided. + set_content_and_release(container, content_cpp); + if (!container.get_content().get_name().equals("ContentDerived")) + throw new RuntimeException("did not get ContentDerived"); + } +} + diff --git a/Examples/test-suite/java/director_smartptr_runme.java b/Examples/test-suite/java/director_smartptr_runme.java index 710ece710..53d68f995 100644 --- a/Examples/test-suite/java/director_smartptr_runme.java +++ b/Examples/test-suite/java/director_smartptr_runme.java @@ -33,6 +33,19 @@ public class director_smartptr_runme { director_smartptr.Foo myFoo2 = new director_smartptr.Foo().makeFoo(); check(myFoo2.pong(), "Foo::pong();Foo::ping()"); check(director_smartptr.Foo.callPong(myFoo2), "Foo::pong();Foo::ping()"); + + director_smartptr.FooDerived myBarFooDerived = new director_smartptr_MyBarFooDerived(); + check(myBarFooDerived.ping(), "director_smartptr_MyBarFooDerived.ping()"); + check(director_smartptr.FooDerived.callPong(myBarFooDerived), "director_smartptr_MyBarFooDerived.pong();director_smartptr_MyBarFooDerived.ping()"); + check(director_smartptr.FooDerived.callUpcall(myBarFooDerived, fooBar), "overrideDerived;Bar::Foo2::Foo2Bar()"); + + director_smartptr.Foo myFoo3 = myBarFoo.makeFoo(); + myFoo3.swigReleaseOwnership(); + myFoo3.swigTakeOwnership(); + director_smartptr.FooDerived myBarFooDerived2 = new director_smartptr_MyBarFooDerived(); + myBarFooDerived2.swigReleaseOwnership(); + myBarFooDerived2.swigTakeOwnership(); + } } @@ -58,3 +71,26 @@ class director_smartptr_MyBarFoo extends director_smartptr.Foo { return new director_smartptr.Foo(); } } + +class director_smartptr_MyBarFooDerived extends director_smartptr.FooDerived { + + @Override + public String ping() { + return "director_smartptr_MyBarFooDerived.ping()"; + } + + @Override + public String pong() { + return "director_smartptr_MyBarFooDerived.pong();" + ping(); + } + + @Override + public String upcall(director_smartptr.FooBar fooBarPtr) { + return "overrideDerived;" + fooBarPtr.FooBarDo(); + } + + @Override + public director_smartptr.Foo makeFoo() { + return new director_smartptr.Foo(); + } +} diff --git a/Examples/test-suite/java/director_thread_runme.java b/Examples/test-suite/java/director_thread_runme.java index c67d4104f..9bc4a93b5 100644 --- a/Examples/test-suite/java/director_thread_runme.java +++ b/Examples/test-suite/java/director_thread_runme.java @@ -30,6 +30,12 @@ class director_thread_Derived extends Foo { } public void do_foo() { + // Not all operating systems can name threads, so only test on those that can + if (Foo.namedThread()) { + String threadName = Thread.currentThread().getName(); + if (!threadName.equals("MyThreadName")) + throw new RuntimeException("Unexpected thread name: " + threadName); + } setVal(getVal() - 1); } } diff --git a/Examples/test-suite/java/doxygen_alias_runme.java b/Examples/test-suite/java/doxygen_alias_runme.java new file mode 100644 index 000000000..e21ed6d19 --- /dev/null +++ b/Examples/test-suite/java/doxygen_alias_runme.java @@ -0,0 +1,32 @@ + +import doxygen_alias.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_alias_runme { + static { + try { + System.loadLibrary("doxygen_alias"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_alias runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_alias"}); + + HashMap wantedComments = new HashMap(); + wantedComments.put("doxygen_alias.doxygen_alias.make_something()", + " A function returning something.
    \n" + + "
    \n" + + " @return A new object which may be null.\n" + + ""); + + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_basic_notranslate_runme.java b/Examples/test-suite/java/doxygen_basic_notranslate_runme.java new file mode 100644 index 000000000..e3d9b0279 --- /dev/null +++ b/Examples/test-suite/java/doxygen_basic_notranslate_runme.java @@ -0,0 +1,102 @@ + +import doxygen_basic_notranslate.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_basic_notranslate_runme { + static { + try { + System.loadLibrary("doxygen_basic_notranslate"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_basic_notranslate runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_basic_notranslate"}); + + HashMap wantedComments = new HashMap(); + wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function3(int)", + " \n" + + " A test for overloaded functions\n" + + " This is function \\b one\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function4()", + " \n" + + " A test of some mixed tag usage\n" + + " \\if CONDITION\n" + + " This \\a code fragment shows us something \\.\n" + + " \\par Minuses:\n" + + " \\arg it's senseless\n" + + " \\arg it's stupid\n" + + " \\arg it's null\n" + + " \n" + + " \\warning This may not work as expected\n" + + " \n" + + " \\code\n" + + " int main() { while(true); }\n" + + " \\endcode\n" + + " \\endif\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function()", + " \n" + + " \\brief\n" + + " Brief description.\n" + + " \n" + + " The comment text\n" + + " \\author Some author\n" + + " \\return Some number\n" + + " \\sa function2\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function5(int)", + " This is a post comment. "); + wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function7(doxygen_basic_notranslate.SWIGTYPE_p_p_p_Shape)", + " \n" + + " Test for a parameter with difficult type\n" + + " (mostly for python)\n" + + " @param a Very strange param\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function3(int, int)", + " \n" + + " A test for overloaded functions\n" + + " This is function \\b two\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function6(int)", + " \n" + + " Test for default args\n" + + " @param a Some parameter, default is 42\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function6()", + " \n" + + " Test for default args\n" + + " @param a Some parameter, default is 42\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function1()", + " Single line comment "); + wantedComments.put("doxygen_basic_notranslate.doxygen_basic_notranslate.function2()", + " \n" + + " A test of a very very very very very very very very very very very very very very very very\n" + + " very very very very very long comment string.\n" + + " \n" + + ""); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_basic_translate_runme.java b/Examples/test-suite/java/doxygen_basic_translate_runme.java new file mode 100644 index 000000000..ab343b560 --- /dev/null +++ b/Examples/test-suite/java/doxygen_basic_translate_runme.java @@ -0,0 +1,101 @@ + +import doxygen_basic_translate.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_basic_translate_runme { + static { + try { + System.loadLibrary("doxygen_basic_translate"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_basic_translate runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_basic_translate"}); + + HashMap wantedComments = new HashMap(); + + wantedComments.put("doxygen_basic_translate.doxygen_basic_translate.function()", + " \n" + + " Brief description.\n" + + " \n" + + " The comment text.\n" + + " @author Some author\n" + + " @return Some number\n" + + " @see function2\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate.doxygen_basic_translate.function2()", + " A test of a very very very very very very very very very very very very very very very very \n" + + " very very very very very long comment string. \n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate.doxygen_basic_translate.function4()", + " A test of some mixed tag usage \n" + + " If: CONDITION {\n" + + " This code fragment shows us something . \n" + + "

    \n" + + "

  • it's senseless \n" + + "
  • it's stupid \n" + + "
  • it's null \n" + + " \n" + + "
  • Warning: This may not work as expected \n" + + " \n" + + " {@code \n" + + "int main() { while(true); } \n" + + "\n" + + "// Test blank line in code block \n" + + " }\n" + + " }\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate.doxygen_basic_translate.function3(int)", + " A test for overloaded functions \n" + + " This is function one \n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate.doxygen_basic_translate.function5(int)", + " This is a post comment. \n" + + ""); + wantedComments.put("doxygen_basic_translate.doxygen_basic_translate.function6(int)", + " Test for default args \n" + + " @param a Some parameter, default is 42" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate.doxygen_basic_translate.function6()", + " Test for default args \n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate.doxygen_basic_translate.function7(doxygen_basic_translate.SWIGTYPE_p_p_p_Shape)", + " Test for a parameter with difficult type \n" + + " (mostly for python) \n" + + " @param a Very strange param \n" + + ""); + wantedComments.put("doxygen_basic_translate.doxygen_basic_translate.function3(int, int)", + " A test for overloaded functions \n" + + " This is function two \n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate.doxygen_basic_translate.Atan2(double, double)", + " Multiple parameters test.\n" + + " \n" + + " @param y Vertical coordinate.\n" + + " @param x Horizontal coordinate.\n" + + " @return Arc tangent of y/x.\n" + + ""); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_basic_translate_style2_runme.java b/Examples/test-suite/java/doxygen_basic_translate_style2_runme.java new file mode 100644 index 000000000..05e51cff8 --- /dev/null +++ b/Examples/test-suite/java/doxygen_basic_translate_style2_runme.java @@ -0,0 +1,101 @@ + +import doxygen_basic_translate_style2.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_basic_translate_style2_runme { + static { + try { + System.loadLibrary("doxygen_basic_translate_style2"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_basic_translate_style2 runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_basic_translate_style2"}); + + HashMap wantedComments = new HashMap(); + + wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function()", + " \n" + + " Brief description.\n" + + " \n" + + " The comment text.\n" + + " @author Some author\n" + + " @return Some number\n" + + " @see function2\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function2()", + " A test of a very very very very very very very very very very very very very very very very \n" + + " very very very very very long comment string. \n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function4()", + " A test of some mixed tag usage \n" + + " If: CONDITION {\n" + + " This code fragment shows us something . \n" + + "

    \n" + + "

  • it's senseless \n" + + "
  • it's stupid \n" + + "
  • it's null \n" + + " \n" + + "
  • Warning: This may not work as expected \n" + + " \n" + + " {@code \n" + + "int main() { while(true); } \n" + + "\n" + + "// Test blank line in code block \n" + + " }\n" + + " }\n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function3(int)", + " A test for overloaded functions \n" + + " This is function one \n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function5(int)", + " This is a post comment. \n" + + ""); + wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function6(int)", + " Test for default args \n" + + " @param a Some parameter, default is 42" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function6()", + " Test for default args \n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function7(doxygen_basic_translate_style2.SWIGTYPE_p_p_p_Shape)", + " Test for a parameter with difficult type \n" + + " (mostly for python) \n" + + " @param a Very strange param \n" + + ""); + wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.function3(int, int)", + " A test for overloaded functions \n" + + " This is function two \n" + + " \n" + + ""); + wantedComments.put("doxygen_basic_translate_style2.doxygen_basic_translate_style2.Atan2(double, double)", + " Multiple parameters test.\n" + + " \n" + + " @param y Vertical coordinate.\n" + + " @param x Horizontal coordinate.\n" + + " @return Arc tangent of y/x.\n" + + ""); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_ignore_runme.java b/Examples/test-suite/java/doxygen_ignore_runme.java new file mode 100644 index 000000000..6250ce525 --- /dev/null +++ b/Examples/test-suite/java/doxygen_ignore_runme.java @@ -0,0 +1,44 @@ + +import doxygen_ignore.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_ignore_runme { + static { + try { + System.loadLibrary("doxygen_ignore"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_ignore runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_ignore"}); + + HashMap wantedComments = new HashMap(); + wantedComments.put("doxygen_ignore.doxygen_ignore.func()", + " A contrived example of ignoring too many commands in one comment.
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + " This is specific to Java.
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + " Command ignored, but anything here is still included.
    \n" + + "
    \n" + + "\n" + + "\n" + + "\n" + + ""); + + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_misc_constructs_runme.java b/Examples/test-suite/java/doxygen_misc_constructs_runme.java new file mode 100644 index 000000000..5d95bd565 --- /dev/null +++ b/Examples/test-suite/java/doxygen_misc_constructs_runme.java @@ -0,0 +1,200 @@ + +import doxygen_misc_constructs.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_misc_constructs_runme { + static { + try { + System.loadLibrary("doxygen_misc_constructs"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_misc_constructs runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_misc_constructs"}); + + HashMap wantedComments = new HashMap(); + + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.getConnection()", + "\n" + + "\n" + + " This function returns connection id.\n" + + "\n" + + ""); + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.getAddress(doxygen_misc_constructs.SWIGTYPE_p_int, int)", + " Returns address of file line.\n" + + " \n" + + " @param fileName name of the file, where the source line is located\n" + + " @param line line number\n" + + " {@link Connection::getId() }
    \n" + + "\n" + + ""); + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.getG_zipCode()", + " Tag endlink must be recognized also when it is the last token\n" + + " in the comment.\n" + + " \n" + + " {@link Connection::getId() }
    \n" + + " {@link debugIdeTraceProfilerCoverageSample.py Python example. }\n" + + "\n" + + ""); + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.setG_zipCode(int)", + " Tag endlink must be recognized also when it is the last token\n" + + " in the comment.\n" + + "\n" + + " {@link Connection::getId() }
    \n" + + " {@link debugIdeTraceProfilerCoverageSample.py Python example. }\n" + + "\n" + + ""); + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.getG_counter()", + " Tag endlink must be recognized also when followed by nonspace character.\n" + + "\n" + + " {@link Connection::getId() }
    \n" + + "\n" + + ""); + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.waitTime(int)", + " Determines how long the isystem.connect should wait for running\n" + + " instances to respond. Only one of lfWaitXXX flags from IConnect::ELaunchFlags\n" + + " may be specified.\n" + + "\n" + + ""); + wantedComments.put("doxygen_misc_constructs.CConnectionConfig", + " This class contains information for connection to winIDEA. Its methods\n" + + " return reference to self, so we can use it like this:\n" + + "
    \n" +
    +    		" CConnectionConfig config = new CConnectionConfig();\n" +
    +    		" config.discoveryPort(5534).dllPath(\"C:\\\\myWinIDEA\\\\connect.dll\").id(\"main\");\n" +
    +    		" 
    \n" + + "\n" + + " All parameters are optional. Set only what is required, default values are\n" + + " used for unspecified parameters.\n" + + "

    \n" + + "\n" + + " {@link advancedWinIDEALaunching.py Python example. }
    \n" + + "\n" + + ""); + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.getAddress(doxygen_misc_constructs.SWIGTYPE_p_int, int, boolean)", + " Returns address of file line.\n" + + "\n" + + " @param fileName name of the file, where the source line is located\n" + + " @param line line number\n" + + " @param isGetSize if set, for every object location both address and size are returned\n" + + "\n" + + " {@link Connection::getId() }
    \n" + + "\n" + + ""); + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.setG_counter(char)", + " Tag endlink must be recognized also when followed by nonspace character.\n" + + "\n" + + " {@link Connection::getId() }
    \n" + + "\n" + + ""); + + wantedComments.put("doxygen_misc_constructs.ClassWithNestedEnum", + " Class description.\n" + + "\n"); + + wantedComments.put("doxygen_misc_constructs.ClassWithNestedEnum.ENested", + " Enum description.\n" + + "\n"); + + wantedComments.put("doxygen_misc_constructs.ClassWithNestedEnum.ENested.ONE", + " desc of one\n"); + + wantedComments.put("doxygen_misc_constructs.ClassWithNestedEnum.ENested.TWO", + " desc of two\n"); + + wantedComments.put("doxygen_misc_constructs.ClassWithNestedEnum.ENested.THREE", + " desc of three\n"); + + wantedComments.put("doxygen_misc_constructs.StructWithReturnComment", + " @return This is a bad place for this tag, but it should be ignored."); + + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.showList()", +" An example of a list in a documentation comment.
    \n" + +"
    \n" + +" - The first item of the list.
    \n" + +" - The second list item, on
    \n" + +" several indented lines,
    \n" + +" showing that the indentation
    \n" + +" is preserved.
    \n" + +" - And the final list item after it.
    \n" + +"
    \n" + +" And this is not a list item any more.\n" + + ""); + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.isNoSpaceValidA()", + " This comment without space after '*' is valid in Doxygen.\n" + + "\n" + + ""); + + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.isNoSpaceValidB()", + " .This comment without space after '*' is valid in Doxygen.\n" + + "\n" + + ""); + + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.backslashA()", + " Backslash followingword is a valid doxygen command. Output contains\n" + + " 'followingword' with 'word' in code font.\n" + + "\n" + + ""); + + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.backslashB()", + " Doxy command without trailing space is ignored - nothing appears\n" + + " on output. Standalone \\ and '\\' get to output.\n" + + " Standalone @ and '@' get to output.\n" + + " Commands \"in quoted \\b strings are treated as plain text\".\n" + + " Commands not recognized by Doxygen are ignored.\n" + + " Backslashes in DOS paths d:and words\n" + + " following them do not appear on output, we must quote them with\n" + + " double quotes: \"d:\\xyz\\qwe\\myfile\", \"@something\". Single quotes do not help:\n" + + " 'd:'. Escaping works: d:\\xyz\\qwe\\myfile. Unix\n" + + " paths of course have no such problems: /xyz/qwe/myfile\n" + + " Commands for escaped symbols:\n" + + " $ @ \\ & ~ < > # % " . :: @text ::text" + + "\n"); + + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.backslashC()", + " Backslash e at end of line froze SWIG\n" + + " with old comment parser.\n" + + " @see MyClass#fun(char,float)\n" + + ""); + + wantedComments.put("doxygen_misc_constructs.doxygen_misc_constructs.cycle(int, java.lang.String)", + " The next line contains expression:\n" + + "

    \n" +
    +    		" ['retVal < 10', 'g_counter == 23 && g_mode & 3']\n" +
    +                " 
    \n" + + "\n" + + " Both words should be emphasized isystem.connect.\n" + + " But not the last period. For example, comma should not be emphasized.\n" + + " Similar for: double colon.\n" + + "\n" + + " Spaces at the start of line should be taken into account:\n" + + " @param id used as prefix in log\n" + + " statements. The default value is empty string, which is OK if\n" + + " there is only one app. instance. Example:\n" + + "
    \n" +
    +                "         ctrl.setBP(\"func1\");\n" +
    +                "     
    \n" + + " If we set the id to main_, we get:\n" + + "
    \n" +
    +                "         main_ctrl.setBP(\"func1\");\n" +
    +                "     
    \n" + + "\n" + + " @param fileName name of the log file\n"); + + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_nested_class_runme.java b/Examples/test-suite/java/doxygen_nested_class_runme.java new file mode 100644 index 000000000..3ffa796f0 --- /dev/null +++ b/Examples/test-suite/java/doxygen_nested_class_runme.java @@ -0,0 +1,48 @@ +import doxygen_nested_class.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_nested_class_runme { + static { + try { + System.loadLibrary("doxygen_nested_class"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_nested_class runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_nested_class"}); + + HashMap wantedComments = new HashMap(); + + wantedComments.put("doxygen_nested_class.DoxOuter()", + " DoxOuter constructor "); + wantedComments.put("doxygen_nested_class.DoxOuter.DoxInner", + " DoxInner class description "); + wantedComments.put("doxygen_nested_class.DoxOuter.DoxInner()", + " DoxInner constructor "); + wantedComments.put("doxygen_nested_class.DoxOuter.DoxInner.setDoxInt(int)", + " doxInt variable "); + wantedComments.put("doxygen_nested_class.DoxOuter.DoxInner.getDoxInt()", + " doxInt variable "); + wantedComments.put("doxygen_nested_class.DoxOuter.DoxInner.doxMethod()", + " doxMethod description "); + wantedComments.put("doxygen_nested_class.DoxOuter.DoxInner.doxStaticMethod()", + " doxStaticMethod description "); + wantedComments.put("doxygen_nested_class.DoxOuter.DoxInner.doxShort", + " doxShort const variable "); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_parsing_enums_proper_runme.java b/Examples/test-suite/java/doxygen_parsing_enums_proper_runme.java new file mode 100644 index 000000000..ef1f06af5 --- /dev/null +++ b/Examples/test-suite/java/doxygen_parsing_enums_proper_runme.java @@ -0,0 +1,66 @@ + +import doxygen_parsing_enums_proper.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_parsing_enums_proper_runme { + static { + try { + System.loadLibrary("doxygen_parsing_enums_proper"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_parsing_enums_proper runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_parsing_enums_proper"}); + + HashMap wantedComments = new HashMap(); + + wantedComments.put("doxygen_parsing_enums_proper.SomeAnotherEnum2.SOME_ITEM_10", + "Post comment for the first item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_proper.SomeAnotherEnum.SOME_ITEM_1", + " The comment for the first item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_proper.SomeAnotherEnum", + " Testing comments before enum items \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_proper.SomeAnotherEnum2.SOME_ITEM_30", + "Post comment for the third item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_proper.SomeAnotherEnum2", + " Testing comments after enum items \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_proper.SomeAnotherEnum.SOME_ITEM_3", + " The comment for the third item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_proper.SomeAnotherEnum.SOME_ITEM_2", + " The comment for the second item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_proper.SomeAnotherEnum2.SOME_ITEM_20", + "Post comment for the second item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_proper.SomeEnumWithTrailingComma.SOME_ITEM_100", + "Post comment after comma."); + wantedComments.put("doxygen_parsing_enums_proper.SomeEnumWithTrailingComma.SOME_ITEM_200", + "Post comment after last comma."); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_parsing_enums_simple_runme.java b/Examples/test-suite/java/doxygen_parsing_enums_simple_runme.java new file mode 100644 index 000000000..85ec0cb55 --- /dev/null +++ b/Examples/test-suite/java/doxygen_parsing_enums_simple_runme.java @@ -0,0 +1,58 @@ + +import doxygen_parsing_enums_simple.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_parsing_enums_simple_runme { + static { + try { + System.loadLibrary("doxygen_parsing_enums_simple"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_parsing_enums_simple runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_parsing_enums_simple"}); + + HashMap wantedComments = new HashMap(); + + wantedComments.put("doxygen_parsing_enums_simple.doxygen_parsing_enums_simpleConstants.SOME_ITEM_30", + "Post comment for the third item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_simple.doxygen_parsing_enums_simpleConstants.SOME_ITEM_3", + " The comment for the third item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_simple.doxygen_parsing_enums_simpleConstants.SOME_ITEM_2", + " The comment for the second item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_simple.doxygen_parsing_enums_simpleConstants.SOME_ITEM_10", + "Post comment for the first item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_simple.doxygen_parsing_enums_simpleConstants.SOME_ITEM_20", + "Post comment for the second item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_simple.doxygen_parsing_enums_simpleConstants.SOME_ITEM_1", + " The comment for the first item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_simple.doxygen_parsing_enums_simpleConstants.SOME_ITEM_100", + "Post comment after comma."); + wantedComments.put("doxygen_parsing_enums_simple.doxygen_parsing_enums_simpleConstants.SOME_ITEM_200", + "Post comment after last comma."); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_parsing_enums_typesafe_runme.java b/Examples/test-suite/java/doxygen_parsing_enums_typesafe_runme.java new file mode 100644 index 000000000..4e5f4b489 --- /dev/null +++ b/Examples/test-suite/java/doxygen_parsing_enums_typesafe_runme.java @@ -0,0 +1,67 @@ + +import doxygen_parsing_enums_typesafe.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_parsing_enums_typesafe_runme { + static { + try { + System.loadLibrary("doxygen_parsing_enums_typesafe"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_parsing_enums_typesafe runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_parsing_enums_typesafe"}); + + HashMap wantedComments = new HashMap(); + + wantedComments.put("doxygen_parsing_enums_typesafe.SomeAnotherEnum.SOME_ITEM_1", + " The comment for the first item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typesafe.SomeAnotherEnum2", + " Testing comments after enum items \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typesafe.SomeAnotherEnum.SOME_ITEM_2", + " The comment for the second item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typesafe.SomeAnotherEnum2.SOME_ITEM_20", + "Post comment for the second item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typesafe.SomeAnotherEnum", + " Testing comments before enum items \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typesafe.SomeAnotherEnum2.SOME_ITEM_10", + "Post comment for the first item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typesafe.SomeAnotherEnum.SOME_ITEM_3", + " The comment for the third item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typesafe.SomeAnotherEnum2.SOME_ITEM_30", + "Post comment for the third item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typesafe.SomeEnumWithTrailingComma.SOME_ITEM_100", + "Post comment after comma."); + wantedComments.put("doxygen_parsing_enums_typesafe.SomeEnumWithTrailingComma.SOME_ITEM_200", + "Post comment after last comma."); + + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_parsing_enums_typeunsafe_runme.java b/Examples/test-suite/java/doxygen_parsing_enums_typeunsafe_runme.java new file mode 100644 index 000000000..428649196 --- /dev/null +++ b/Examples/test-suite/java/doxygen_parsing_enums_typeunsafe_runme.java @@ -0,0 +1,66 @@ + +import doxygen_parsing_enums_typeunsafe.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_parsing_enums_typeunsafe_runme { + static { + try { + System.loadLibrary("doxygen_parsing_enums_typeunsafe"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_parsing_enums_typeunsafe runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_parsing_enums_typeunsafe"}); + + HashMap wantedComments = new HashMap(); + + wantedComments.put("doxygen_parsing_enums_typeunsafe.SomeAnotherEnum.SOME_ITEM_2", + " The comment for the second item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typeunsafe.SomeAnotherEnum.SOME_ITEM_3", + " The comment for the third item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typeunsafe.SomeAnotherEnum.SOME_ITEM_1", + " The comment for the first item \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typeunsafe.SomeAnotherEnum2.SOME_ITEM_20", + "Post comment for the second item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typeunsafe.SomeAnotherEnum", + " Testing comments before enum items \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typeunsafe.SomeAnotherEnum2", + " Testing comments after enum items \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typeunsafe.SomeAnotherEnum2.SOME_ITEM_30", + "Post comment for the third item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typeunsafe.SomeAnotherEnum2.SOME_ITEM_10", + "Post comment for the first item \n" + + ""); + wantedComments.put("doxygen_parsing_enums_typeunsafe.SomeEnumWithTrailingComma.SOME_ITEM_100", + "Post comment after comma."); + wantedComments.put("doxygen_parsing_enums_typeunsafe.SomeEnumWithTrailingComma.SOME_ITEM_200", + "Post comment after last comma."); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_parsing_runme.java b/Examples/test-suite/java/doxygen_parsing_runme.java new file mode 100644 index 000000000..d58b1f486 --- /dev/null +++ b/Examples/test-suite/java/doxygen_parsing_runme.java @@ -0,0 +1,141 @@ + +import doxygen_parsing.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_parsing_runme { + static { + try { + System.loadLibrary("doxygen_parsing"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_parsing runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_parsing"}); + + HashMap wantedComments = new HashMap(); + + wantedComments.put("doxygen_parsing.SomeAnotherClass", + " SomeAnotherClass description"); + wantedComments.put("doxygen_parsing.SomeAnotherClass(int)", + " First overloaded constructor."); + wantedComments.put("doxygen_parsing.SomeAnotherClass(java.lang.String)", + " Second overloaded constructor."); + wantedComments.put("doxygen_parsing.SomeAnotherClass.getClassAttr()", + " The class attribute comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherClass.setClassAttr3(int)", + "The class attribute post-comment with details \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherStruct.setStructAttr3(int)", + "The struct attribute post-comment with details \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherClass.classMethodExtended2(int, int)", + " The class method with parameter \n" + + " \n" + + " @param a Parameter a \n" + + " @param b Parameter b \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeStruct", + " The struct comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.doxygen_parsing.setSomeVar(int)", + " The var comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherStruct.structMethod()", + " The struct method comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.doxygen_parsing.someFunction()", + " The function comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherClass.classMethodExtended(int, int)", + " The class method with parameter \n" + + " \n" + + " @param a Parameter a \n" + + " @param b Parameter b \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherClass.setClassAttr(int)", + " The class attribute comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherStruct.structMethodExtended(int, int)", + " The struct method with parameter \n" + + " \n" + + " @param a Parameter a \n" + + " @param b Parameter b \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherStruct.getStructAttr()", + " The struct attribute comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeClass", + " The class comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherStruct.getStructAttr3()", + "The struct attribute post-comment with details \n" + + ""); + wantedComments.put("doxygen_parsing.doxygen_parsing.getSomeVar()", + " The var comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherStruct.setStructAttr2(int)", + "The struct attribute post-comment \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherClass.getClassAttr2()", + "The class attribute post-comment \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherStruct.getStructAttr2()", + "The struct attribute post-comment \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherStruct.setStructAttr(int)", + " The struct attribute comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeEnum", + " The enum comment \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherClass.getClassAttr3()", + "The class attribute post-comment with details \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherClass.classMethod()", + " The class method comment.
    \n" + + "
    \n" + + " {@link SomeAnotherClass#classMethodExtended(int,int) a link text }\n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherStruct.structMethodExtended2(int, int)", + " The struct method with parameter \n" + + " \n" + + " @param a Parameter a \n" + + " @param b Parameter b \n" + + " \n" + + ""); + wantedComments.put("doxygen_parsing.SomeAnotherClass.setClassAttr2(int)", + "The class attribute post-comment \n" + + ""); + wantedComments.put("doxygen_parsing.doxygen_parsingConstants.CONSTANT_VALUE", + "The constant comment \n" + + ""); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_translate_all_tags_runme.java b/Examples/test-suite/java/doxygen_translate_all_tags_runme.java new file mode 100644 index 000000000..d5c533f4e --- /dev/null +++ b/Examples/test-suite/java/doxygen_translate_all_tags_runme.java @@ -0,0 +1,159 @@ + +import doxygen_translate_all_tags.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_translate_all_tags_runme { + static { + try { + System.loadLibrary("doxygen_translate_all_tags"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_translate_all_tags runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_translate_all_tags"}); + + HashMap wantedComments = new HashMap(); + + wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func01(int)", + " Hello \n\n\n" + + " \n\n\n" + + "
  • some list item
  • \n\n" + + " This is attention!\n" + + " You were warned!\n" + + " @author lots of them\n" + + " @author Zubr\n\n" + + " boldword\n\n" + + " Some brief description,\n" + + " extended to many lines.\n\n" + + " Not everything works right now...\n" + + " codeword\n\n\n\n\n\n" + + " citationword\n" + + " {@code some test code }\n\n" + + " Code immediately following text. Pydoc translation must add an\n" + + " empty line before:\n" + + " {@code more test code }"); + + wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func02(int)", + " Conditional comment: SOMECONDITION \n" + + " Some conditional comment \n" + + " End of conditional comment.\n" + + " Copyright: some copyright \n" + + " 1970 - 2012 \n" + + " @deprecated Now use another function \n" + + " This is very large \n" + + " and detailed description of some thing \n"); + + wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func03(int)", + " Comment for func03().\n" + + " italicword \n" + + " emphazedWord \n" + + " @ example someFile.txt\n" + + " Some details on using the example"); + + wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func04(int)", + " @exception SuperError \n" + + " \\sqrt{(x_2-x_1)^2+(y_2-y_1)^2} \n" + + " \\sqrt{(x_2-x_1)^2+(y_2-y_1)^2} \n" + + " \\sqrt{(x_2-x_1)^2+(y_2-y_1)^2} \n\n" + + "Math immediately following text. Pydoc translation must add an\n" + + "empty line before:\n\n" + + " \\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}\n" + + " This will only appear in hmtl \n"); + + wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func05(int)", + " If: ANOTHERCONDITION {\n" + + " First part of comment \n" + + " If: SECONDCONDITION {\n" + + " Nested condition text \n" + + " }Else if: THIRDCONDITION {\n" + + " The third condition text \n" + + " }Else: {The last text block \n" + + " }\n" + + " }Else: {Second part of comment \n" + + " If: CONDITION {\n" + + " Second part extended \n" + + " }\n" + + " }\n" + + " If not: SOMECONDITION {\n" + + " This is printed if not \n" + + " }\n" + + " \"Hello,\n" + + " Some text \n" + + " describing invariant. \n"); + + wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func06(int)", + " Comment for func06().\n" + + " This will only appear in LATeX \n" + + "
      \n" + + "
    • Some unordered list \n" + + "
    • With lots of items \n" + + "
    • lots of lots of items \n" + + "
    \n" + + " {@link someMember Some description follows }\n" + + " This will only appear in man\n"); + + wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func07(int)", + " Comment for func07().\n" + + " Note: Here \n" + + " is the note! \n" + + " This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.\n" + + " someword \n" + + " @package superPackage \n" + + "

    \n" + + " The paragraph text. \n" + + " Maybe even multiline \n" + + "

    \n" + + " @param a the first param\n"); + + wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func08(int)", + "\n" + + "Text after anchor.\n" + + "Anchor description\n" + + "someAnchor not quoted text is not part of ref tag\n" + + "someAnchor\n" + + " Remarks: Some remark text \n" + + " Remarks: Another remarks section \n" + + " @return Whatever \n" + + " @return it \n" + + " @return may return \n"); + + wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func09(int)", + " This will only appear in RTF \n" + + " @see someOtherMethod \n" + + " @see function \n" + + " Same as \n" + + " brief description \n" + + " @since version 0.0.0.1 \n" + + " @throws superException \n" + + " @throws RuntimeError \n"); + + wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func10(int, float)", + " TODO: Some very important task \n" + + " @param b B is mentioned again... \n" + + " {@literal \n" + + "very long \n" + + "text with tags \n" + + " }\n" + + " @version 0.0.0.2 \n" + + " Warning: This is senseless! \n" + + " This will only appear in XML \n" + + " Here goes test of symbols: \n" + + " $ @ \\ & ~ < > # % " . :: \n" + + " And here goes simple text \n" + + ""); + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/doxygen_translate_links_runme.java b/Examples/test-suite/java/doxygen_translate_links_runme.java new file mode 100644 index 000000000..6d74e16fe --- /dev/null +++ b/Examples/test-suite/java/doxygen_translate_links_runme.java @@ -0,0 +1,69 @@ + +import doxygen_translate_links.*; +import com.sun.javadoc.*; +import java.util.HashMap; + +public class doxygen_translate_links_runme { + static { + try { + System.loadLibrary("doxygen_translate_links"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_translate_links runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_translate_links"}); + + HashMap wantedComments = new HashMap(); + + + wantedComments.put("doxygen_translate_links.doxygen_translate_links.function()", + " \n" + + " Testing typenames converting in @ link \n" + + " \n" + + " {@link superFunc(int,String) \n" + + " Test for std_string member \n" + + " }\n" + + " \n" + + " {@link superFunc(int,int,SWIGTYPE_p_void) \n" + + " Test for simple types \n" + + " }\n" + + " \n" + + " {@link superFunc(SWIGTYPE_p_p_Shape) \n" + + " Test for custom types \n" + + " }\n" + + " \n" + + " {@link superFunc(SWIGTYPE_p_p_p_int) \n" + + " Test for complex types \n" + + " }\n" + + " \n" + + " same works for 'See also:' links: \n" + + " \n" + + " @see superFunc(int,String)\n" + + " @see superFunc(int,int,SWIGTYPE_p_void)\n" + + " @see superFunc(SWIGTYPE_p_p_Shape)\n" + + " @see superFunc(SWIGTYPE_p_p_p_int)\n" + + " \n" + + " some failing params: \n" + + " \n" + + " @see superFunc() \n" + + " @see superFunc() \n" + + " @see superFunc() \n" + + " \n" + + " \n" + + ""); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} \ No newline at end of file diff --git a/Examples/test-suite/java/doxygen_translate_runme.java b/Examples/test-suite/java/doxygen_translate_runme.java new file mode 100644 index 000000000..55e5d23d3 --- /dev/null +++ b/Examples/test-suite/java/doxygen_translate_runme.java @@ -0,0 +1,279 @@ + +import doxygen_translate.*; +import com.sun.javadoc.*; +import java.util.HashMap; +import java.util.Map; + +public class doxygen_translate_runme { + static { + try { + System.loadLibrary("doxygen_translate"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + /* + Here we are using internal javadoc tool, it accepts the name of the class as paramterer, + and calls the start() method of that class with parsed information. + */ + CommentParser parser = new CommentParser(); + com.sun.tools.javadoc.Main.execute("doxygen_translate runtime test", + "CommentParser", + new String[]{"-quiet", "doxygen_translate"}); + + Map wantedComments = new HashMap(); + + wantedComments.put("doxygen_translate.doxygen_translate.function(int, float)", + " Hello \n" + + " \n" + + "
  • some list item
  • \n" + + " \n" + + " @author lots of them \n" + + " \n" + + " @author Zubr \n" + + " \n" + + " boldword \n" + + " \n" + + " codeword \n" + + " \n" + + " citationword \n" + + " \n" + + " {@code some test code }\n" + + " \n" + + " Conditional comment: SOMECONDITION \n" + + " Some conditional comment \n" + + " End of conditional comment.\n" + + " \n" + + " Copyright: some copyright \n" + + " \n" + + " @deprecated Now use another function \n" + + " \n" + + " italicword \n" + + " \n" + + " @ example someFile.txt\n" + + " Some details on using the example\n" + + " \n" + + " @exception SuperError \n" + + " \n" + + " If: ANOTHERCONDITION {\n" + + " First part of comment \n" + + " If: SECONDCONDITION {\n" + + " Nested condition text}\n" + + " Else if: THIRDCONDITION {\n" + + " The third condition text}\n" + + " Else: {The last text block}}\n" + + " \n" + + " Else: {Second part of comment \n" + + " If: CONDITION {\n" + + " Second part extended}}\n" + + " \n" + + " \n" + + " \n" + + " If not: SOMECONDITION {\n" + + " This is printed if not}\n" + + " \n" + + " \n" + + " \"Hello,\n" + + " \n" + + "
      \n" + + " \n" + + "
    • Some unordered list
    • \n" + + "
    • With lots of items
    • \n" + + "
    • lots of lots of items
    • \n" + + " \n" + + "
    \n" + + " \n" + + " {@link someMember Some description follows }\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " Note: Here \n" + + " is the note! \n" + + " \n" + + " This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.\n" + + " \n" + + " someword \n" + + " \n" + + " @package superPackage \n" + + " \n" + + "

    \n" + + " The paragraph text. \n" + + " Maybe even multiline

    \n" + + " \n" + + " @param a the first param \n" + + " \n" + + " Remarks: Some remark text \n" + + " \n" + + " Remarks: Another remarks section \n" + + " \n" + + " @return Whatever \n" + + " \n" + + " @return it \n" + + " \n" + + " @return may return \n" + + " \n" + + " @see someOtherMethod \n" + + " \n" + + " @see function \n" + + " \n" + + " @since version 0.0.0.1 \n" + + " \n" + + " @throws superException \n" + + " \n" + + " @throws RuntimeError \n" + + " \n" + + " TODO: Some very important task \n" + + " \n" + + " @param b B is mentioned again... \n" + + " \n" + + " {@literal \n" + + "very long \n" + + "text with tags \n" + + " }\n" + + " \n" + + " @version 0.0.0.2 \n" + + " \n" + + " Warning: This is senseless! \n" + + " \n" + + " Here goes test of symbols: \n" + + " $ @ \\ & ~ < > # % " . :: \n" + + " \n" + + " And here goes simple text \n" + + " \n" + + ""); + + wantedComments.put("doxygen_translate.doxygen_translate.htmlFunction(int, float)", + " Test for html tags. See Doxygen doc for list of tags recognized by Doxygen. \n" + + " \n" + + " This is link \n" + + " bold \n" + + "
    \n" + + " Quotation block. \n" + + "
    \n" + + "
    \n" + + "
    center
    \n" + + " this is code \n" + + "\n" + + "
    \n" + + "
    Starts an item title.
    \n" + + "
    Starts an item description.
    \n" + + "
    \n" + + "\n" + + " Starts a piece of text displayed in a typewriter font. \n" + + " \n" + + "
    Starts a section with a specific style (HTML only) \n" + + "
    \n" + + " Starts a piece of text displayed in an italic font. \n" + + "\n" + + "
    'Form' does not generate any output. \n" + + "
    \n" + + "
    \n" + + "

    Heading 1 \n" + + "

    \n" + + "

    Heading 2 \n" + + "

    \n" + + "

    Heading 3 \n" + + "

    \n" + + " Starts a piece of text displayed in an italic font. \n" + + " Input tag. \n" + + " \n" + + " \n" + + " Meta tag. \n" + + " Multicol is ignored by doxygen. \n" + + " \n" + + " \n" + + "
      \n" + + "
    1. List item 1.
    2. \n" + + "
    3. List item 2.
    4. \n" + + "
    \n" + + " \n" + + "

    Starts a new paragraph. \n" + + "

    \n" + + "
     Starts a preformatted fragment.                                                \n" +
    +    		" 
    \n" + + " Starts a section of text displayed in a smaller font. \n" + + " \n" + + " Starts an inline text fragment with a specific style. \n" + + " \n" + + " Starts a section of bold text. \n" + + " Starts a piece of text displayed in subscript. \n" + + " Starts a piece of text displayed in superscript. \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    Animals
    Column 1 Column 2
    cow dog
    cat mouse
    horse parrot
    \n" + + " \n" + + " Starts a piece of text displayed in a typewriter font. \n" + + " \n" + + " Starts a piece of text displayed in a typewriter font. \n" + + " \n" + + " \n" + + "
      \n" + + "
    • List item 1.
    • \n" + + "
    • List item 2.
    • \n" + + "
    • List item 3.
    • \n" + + "
    \n" + + " \n" + + " Starts a piece of text displayed in an italic font. \n" + + " \n" + + "\n" + + "underlined \\b bold text - doxy commands are ignored inside 'htmlonly' section \n" + + "\n" + + ""); + + wantedComments.put("doxygen_translate.doxygen_translate.htmlTableFunction(int)", + "The meaning of flags:\n" + + "\n" + + " @param byFlags bits marking required items:\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    Size in bits Items Required
    1 - 8 1
    9 - 16 2
    17 - 32 4
    \n" + + " Almost all combinations of above flags are supported by\n" + + " htmlTable... functions.\n" + + ""); + + + wantedComments.put("doxygen_translate.doxygen_translate.htmlEntitiesFunction(int, float)", + "All entities are treated as commands © ™ ®\n" + + "should work also<in text \n" + + "> \n" + + "& \n" + + "' \n" + + "" \n" + + "‘ \n" + + "’ \n" + + "“ \n" + + "” \n" + + "– \n" + + "— \n" + + "  \n" + + "× \n" + + "− \n" + + "⋅ \n" + + "∼ \n" + + "≤ \n" + + "≥ \n" + + "← \n" + + "→ \n" + + "Not an html entity - ignored by Doxygen. \n" + + "Not an &text html entity - ampersand is replaced with entity.\n" + + ""); + + // and ask the parser to check comments for us + System.exit(parser.check(wantedComments)); + } +} diff --git a/Examples/test-suite/java/enum_macro_runme.java b/Examples/test-suite/java/enum_macro_runme.java index 4ac7409ee..c05793347 100644 --- a/Examples/test-suite/java/enum_macro_runme.java +++ b/Examples/test-suite/java/enum_macro_runme.java @@ -88,6 +88,30 @@ public class enum_macro_runme { { Greeks13 a = null; } + { + Greeks15 a = Greeks15.alpha15; + a = Greeks15.beta15; + a = Greeks15.theta15; + a = Greeks15.delta15; + if (a.swigValue() != 153) + throw new RuntimeException("Greeks15"); + } + { + Greeks16 a = Greeks16.alpha16; + a = Greeks16.beta16; + a = Greeks16.theta16; + a = Greeks16.delta16; + if (a.swigValue() != 163) + throw new RuntimeException("Greeks16"); + } + { + Greeks17 a = Greeks17.alpha17; + a = Greeks17.beta17; + a = Greeks17.theta17; + a = Greeks17.delta17; + if (a.swigValue() != 173) + throw new RuntimeException("Greeks17"); + } } } diff --git a/Examples/test-suite/java/extend_template_method_runme.java b/Examples/test-suite/java/extend_template_method_runme.java new file mode 100644 index 000000000..e957be0bd --- /dev/null +++ b/Examples/test-suite/java/extend_template_method_runme.java @@ -0,0 +1,63 @@ + +import extend_template_method.*; + +public class extend_template_method_runme { + + static { + try { + System.loadLibrary("extend_template_method"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + { + ExtendMe em = new ExtendMe(); + + { + double ret_double = em.do_stuff_double(1, 1.1); + if (ret_double != 1.1) + throw new RuntimeException("double failed " + ret_double); + String ret_string = em.do_stuff_string(1, "hello there"); + if (!ret_string.equals("hello there")) + throw new RuntimeException("string failed " + ret_string); + } + { + double ret_double = em.do_overloaded_stuff(1.1); + if (ret_double != 1.1) + throw new RuntimeException("double failed " + ret_double); + String ret_string = em.do_overloaded_stuff("hello there"); + if (!ret_string.equals("hello there")) + throw new RuntimeException("string failed " + ret_string); + } + if (ExtendMe.static_method(123) != 123) + throw new RuntimeException("static_method failed"); + ExtendMe em2 = new ExtendMe(123); + } + { + TemplateExtend em = new TemplateExtend(); + + { + double ret_double = em.do_template_stuff_double(1, 1.1); + if (ret_double != 1.1) + throw new RuntimeException("double failed " + ret_double); + String ret_string = em.do_template_stuff_string(1, "hello there"); + if (!ret_string.equals("hello there")) + throw new RuntimeException("string failed " + ret_string); + } + { + double ret_double = em.do_template_overloaded_stuff(1.1); + if (ret_double != 1.1) + throw new RuntimeException("double failed " + ret_double); + String ret_string = em.do_template_overloaded_stuff("hello there"); + if (!ret_string.equals("hello there")) + throw new RuntimeException("string failed " + ret_string); + } + if (TemplateExtend.static_template_method(123) != 123) + throw new RuntimeException("static_template_method failed"); + TemplateExtend em2 = new TemplateExtend(123); + } + } +} diff --git a/Examples/test-suite/java/java_director_assumeoverride_runme.java b/Examples/test-suite/java/java_director_assumeoverride_runme.java index e876a79c9..6c4d6918e 100644 --- a/Examples/test-suite/java/java_director_assumeoverride_runme.java +++ b/Examples/test-suite/java/java_director_assumeoverride_runme.java @@ -18,7 +18,7 @@ public class java_director_assumeoverride_runme { public static void main(String argv[]) { OverrideMe overrideMe = new MyOverrideMe(); - // MyOverrideMe doesn't actually override func(), but because assumeoverride + // MyOverrideMe doesn't actually override funk(), but because assumeoverride // was set to true, the C++ side will believe it was overridden. if (!java_director_assumeoverride.isFuncOverridden(overrideMe)) { throw new RuntimeException ( "isFuncOverridden()" ); diff --git a/Examples/test-suite/java/java_director_exception_feature_nspace_runme.java b/Examples/test-suite/java/java_director_exception_feature_nspace_runme.java index ea7da5c1a..884b04c6e 100644 --- a/Examples/test-suite/java/java_director_exception_feature_nspace_runme.java +++ b/Examples/test-suite/java/java_director_exception_feature_nspace_runme.java @@ -126,19 +126,28 @@ public class java_director_exception_feature_nspace_runme { try { b.genericpong(1); fail("No exception thrown in genericpong(1)"); } catch (MyJavaException1 e) { failif( ! java_director_exception_feature_nspace_Consts.GENERICPONGEXCP1.equals(e.getMessage()), "Expected exception has unexpected message: '" + e.getMessage() + "'"); + StackTraceElement[] st = e.getStackTrace(); + failif( st.length != 5, "Stack length is only " + st.length); + failif( ! st[0].toString().startsWith("java_director_exception_feature_nspace_MyFooDirectorImpl.genericpong(java_director_exception_feature_nspace_runme.java:"), "Incorrect top of stack: " + st[0]); } try { b.genericpong(2); fail("No exception thrown in genericpong(2)");} catch (java_director_exception_feature_nspace_NewCheckedException e) { failif( ! java_director_exception_feature_nspace_Consts.GENERICPONGEXCP2.equals(e.getMessage()), "Expected exception has unexpected message: '" + e.getMessage() + "'"); + StackTraceElement[] st = e.getStackTrace(); + failif( st.length != 5, "Stack length is only " + st.length); + failif( ! st[0].toString().startsWith("java_director_exception_feature_nspace_MyFooDirectorImpl.genericpong(java_director_exception_feature_nspace_runme.java:"), "Incorrect top of stack: " + st[0]); } try { b.genericpong(3); fail("No exception thrown in genericpong(3)");} catch (java_director_exception_feature_nspace_NewUncheckedException e) { failif( ! java_director_exception_feature_nspace_Consts.GENERICPONGEXCP3.equals(e.getMessage()), "Expected exception has unexpected message: '" + e.getMessage() + "'"); + StackTraceElement[] st = e.getStackTrace(); + failif( st.length != 5, "Stack length is only " + st.length); + failif( ! st[0].toString().startsWith("java_director_exception_feature_nspace_MyFooDirectorImpl.genericpong(java_director_exception_feature_nspace_runme.java:"), "Incorrect top of stack: " + st[0]); } try { b.genericpong(4); fail("No exception thrown in genericpong(4)");} catch (RuntimeException e) { - failif ( e.getClass() != RuntimeException.class, "Exception " + e + " is not exactly RumtimeException"); - failif( ! java_director_exception_feature_nspace_Consts.GENERICPONGEXCP4.equals(e.getMessage()), "Expected exception has unexpected message: '" + e.getMessage() + "'"); + failif ( e.getClass() != RuntimeException.class, "Exception " + e + " is not exactly RuntimeException"); + failif( ! "Unspecified DirectorException message".equals(e.getMessage()), "Expected exception has unexpected message: '" + e.getMessage() + "'"); } } catch (Exception e) { diff --git a/Examples/test-suite/java/java_director_exception_feature_runme.java b/Examples/test-suite/java/java_director_exception_feature_runme.java index 2e919c18a..d9763c992 100644 --- a/Examples/test-suite/java/java_director_exception_feature_runme.java +++ b/Examples/test-suite/java/java_director_exception_feature_runme.java @@ -127,19 +127,28 @@ public class java_director_exception_feature_runme { try { b.genericpong(1); fail("No exception thrown in genericpong(1)"); } catch (MyJavaException1 e) { failif( ! java_director_exception_feature_Consts.GENERICPONGEXCP1.equals(e.getMessage()), "Expected exception has unexpected message: '" + e.getMessage() + "'"); + StackTraceElement[] st = e.getStackTrace(); + failif( st.length != 5, "Stack length is only " + st.length); + failif( ! st[0].toString().startsWith("java_director_exception_feature_MyFooDirectorImpl.genericpong(java_director_exception_feature_runme.java:"), "Incorrect top of stack: " + st[0]); } try { b.genericpong(2); fail("No exception thrown in genericpong(2)");} catch (NewCheckedException e) { failif( ! java_director_exception_feature_Consts.GENERICPONGEXCP2.equals(e.getMessage()), "Expected exception has unexpected message: '" + e.getMessage() + "'"); + StackTraceElement[] st = e.getStackTrace(); + failif( st.length != 5, "Stack length is only " + st.length); + failif( ! st[0].toString().startsWith("java_director_exception_feature_MyFooDirectorImpl.genericpong(java_director_exception_feature_runme.java:"), "Incorrect top of stack: " + st[0]); } try { b.genericpong(3); fail("No exception thrown in genericpong(3)");} catch (NewUncheckedException e) { failif( ! java_director_exception_feature_Consts.GENERICPONGEXCP3.equals(e.getMessage()), "Expected exception has unexpected message: '" + e.getMessage() + "'"); + StackTraceElement[] st = e.getStackTrace(); + failif( st.length != 5, "Stack length is only " + st.length); + failif( ! st[0].toString().startsWith("java_director_exception_feature_MyFooDirectorImpl.genericpong(java_director_exception_feature_runme.java:"), "Incorrect top of stack: " + st[0]); } try { b.genericpong(4); fail("No exception thrown in genericpong(4)");} catch (RuntimeException e) { - failif ( e.getClass() != RuntimeException.class, "Exception " + e + " is not exactly RumtimeException"); - failif( ! java_director_exception_feature_Consts.GENERICPONGEXCP4.equals(e.getMessage()), "Expected exception has unexpected message: '" + e.getMessage() + "'"); + failif ( e.getClass() != RuntimeException.class, "Exception " + e + " is not exactly RuntimeException"); + failif( ! "Unspecified DirectorException message".equals(e.getMessage()), "Expected exception has unexpected message: '" + e.getMessage() + "'"); } } diff --git a/Examples/test-suite/java/java_director_typemaps_ptr_runme.java b/Examples/test-suite/java/java_director_typemaps_ptr_runme.java new file mode 100644 index 000000000..c387270cd --- /dev/null +++ b/Examples/test-suite/java/java_director_typemaps_ptr_runme.java @@ -0,0 +1,200 @@ +// Test director pointer typemaps in typemaps.i - similar to java_director_typemaps.i testcase + +import java_director_typemaps_ptr.*; +import java.math.BigInteger; + +public class java_director_typemaps_ptr_runme { + + static { + try { + System.loadLibrary("java_director_typemaps_ptr"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + + public static void main(String argv[]) { + java_director_typemaps_ptr_MyQuux myquux = new java_director_typemaps_ptr_MyQuux(); + Quux quux = myquux; + quux.etest(); + myquux.testing_nulls = true; + quux.nulltest(); + } +} + +class java_director_typemaps_ptr_MyQuux extends Quux { + public java_director_typemaps_ptr_MyQuux() { + super(); + } + public boolean testing_nulls = false; + + public void director_method_output( + boolean[] bool_arg, + + byte[] signed_char_arg, + short[] unsigned_char_arg, + + short[] short_arg, + int[] unsigned_short_arg, + + int[] int_arg, + long[] unsigned_int_arg, + + int[] long_arg, + long[] unsigned_long_arg, + + long[] long_long_arg, + // BigInteger[] unsigned_long_long_arg, + + float[] float_arg, + double[] double_arg) + { + if (testing_nulls) { + if (bool_arg != null) throw new RuntimeException("not null bool_arg"); + if (signed_char_arg != null) throw new RuntimeException("not null signed_char_arg"); + if (unsigned_char_arg != null) throw new RuntimeException("not null unsigned_char_arg"); + if (short_arg != null) throw new RuntimeException("not null short_arg"); + if (unsigned_short_arg != null) throw new RuntimeException("not null unsigned_short_arg"); + if (int_arg != null) throw new RuntimeException("not null int_arg"); + if (unsigned_int_arg != null) throw new RuntimeException("not null unsigned_int_arg"); + if (long_arg != null) throw new RuntimeException("not null long_arg"); + if (unsigned_long_arg != null) throw new RuntimeException("not null unsigned_long_arg"); + if (long_long_arg != null) throw new RuntimeException("not null long_long_arg"); + // if (unsigned_long_long_arg != null) throw new RuntimeException("not null unsigned_long_long_arg"); + if (float_arg != null) throw new RuntimeException("not null float_arg"); + if (double_arg != null) throw new RuntimeException("not null double_arg"); + } + if (bool_arg != null) bool_arg[0] = true; + if (signed_char_arg != null) signed_char_arg[0] = 1; + if (unsigned_char_arg != null) unsigned_char_arg[0] = 2; + if (short_arg != null) short_arg[0] = 3; + if (unsigned_short_arg != null) unsigned_short_arg[0] = 4; + if (int_arg != null) int_arg[0] = 5; + if (unsigned_int_arg != null) unsigned_int_arg[0] = 6; + if (long_arg != null) long_arg[0] = 7; + if (unsigned_long_arg != null) unsigned_long_arg[0] = 8; + if (long_long_arg != null) long_long_arg[0] = 9; + // if (unsigned_long_long_arg != null) unsigned_long_long_arg[0] = 10; + if (float_arg != null) float_arg[0] = 11; + if (double_arg != null) double_arg[0] = 12; + } + + public void director_method_inout( + boolean[] bool_arg, + + byte[] signed_char_arg, + short[] unsigned_char_arg, + + short[] short_arg, + int[] unsigned_short_arg, + + int[] int_arg, + long[] unsigned_int_arg, + + int[] long_arg, + long[] unsigned_long_arg, + + long[] long_long_arg, + // BigInteger[] unsigned_long_long_arg, + + float[] float_arg, + double[] double_arg) + { + if (testing_nulls) { + if (bool_arg != null) throw new RuntimeException("not null bool_arg"); + if (signed_char_arg != null) throw new RuntimeException("not null signed_char_arg"); + if (unsigned_char_arg != null) throw new RuntimeException("not null unsigned_char_arg"); + if (short_arg != null) throw new RuntimeException("not null short_arg"); + if (unsigned_short_arg != null) throw new RuntimeException("not null unsigned_short_arg"); + if (int_arg != null) throw new RuntimeException("not null int_arg"); + if (unsigned_int_arg != null) throw new RuntimeException("not null unsigned_int_arg"); + if (long_arg != null) throw new RuntimeException("not null long_arg"); + if (unsigned_long_arg != null) throw new RuntimeException("not null unsigned_long_arg"); + if (long_long_arg != null) throw new RuntimeException("not null long_long_arg"); + // if (unsigned_long_long_arg != null) throw new RuntimeException("not null unsigned_long_long_arg"); + if (float_arg != null) throw new RuntimeException("not null float_arg"); + if (double_arg != null) throw new RuntimeException("not null double_arg"); + } else { + if (bool_arg[0]) throw new RuntimeException("unexpected value for bool_arg"); + if (signed_char_arg[0] != 101) throw new RuntimeException("unexpected value for signed_char_arg"); + if (unsigned_char_arg[0] != 101) throw new RuntimeException("unexpected value for unsigned_char_arg"); + if (short_arg[0] != 101) throw new RuntimeException("unexpected value for short_arg"); + if (unsigned_short_arg[0] != 101) throw new RuntimeException("unexpected value for unsigned_short_arg"); + if (int_arg[0] != 101) throw new RuntimeException("unexpected value for int_arg"); + if (unsigned_int_arg[0] != 101) throw new RuntimeException("unexpected value for unsigned_int_arg"); + if (long_arg[0] != 101) throw new RuntimeException("unexpected value for long_arg"); + if (unsigned_long_arg[0] != 101) throw new RuntimeException("unexpected value for unsigned_long_arg"); + if (long_long_arg[0] != 101) throw new RuntimeException("unexpected value for long_long_arg"); + // if (unsigned_long_long_arg[0] != 101) throw new RuntimeException("unexpected value for unsigned_long_long_arg"); + if (float_arg[0] != 101) throw new RuntimeException("unexpected value for float_arg"); + if (double_arg[0] != 101) throw new RuntimeException("unexpected value for double_arg"); + } + + if (bool_arg != null) bool_arg[0] = false; + if (signed_char_arg != null) signed_char_arg[0] = 11; + if (unsigned_char_arg != null) unsigned_char_arg[0] = 12; + if (short_arg != null) short_arg[0] = 13; + if (unsigned_short_arg != null) unsigned_short_arg[0] = 14; + if (int_arg != null) int_arg[0] = 15; + if (unsigned_int_arg != null) unsigned_int_arg[0] = 16; + if (long_arg != null) long_arg[0] = 17; + if (unsigned_long_arg != null) unsigned_long_arg[0] = 18; + if (long_long_arg != null) long_long_arg[0] = 19; + // if (unsigned_long_long_arg != null) unsigned_long_long_arg[0] = 110; + if (float_arg != null) float_arg[0] = 111; + if (double_arg != null) double_arg[0] = 112; + } + + public void director_method_nameless_args( + boolean[] bool_arg, + + byte[] signed_char_arg, + short[] unsigned_char_arg, + + short[] short_arg, + int[] unsigned_short_arg, + + int[] int_arg, + long[] unsigned_int_arg, + + int[] long_arg, + long[] unsigned_long_arg, + + long[] long_long_arg, + // BigInteger[] unsigned_long_long_arg, + + float[] float_arg, + double[] double_arg) + { + if (testing_nulls) { + if (bool_arg != null) throw new RuntimeException("not null bool_arg"); + if (signed_char_arg != null) throw new RuntimeException("not null signed_char_arg"); + if (unsigned_char_arg != null) throw new RuntimeException("not null unsigned_char_arg"); + if (short_arg != null) throw new RuntimeException("not null short_arg"); + if (unsigned_short_arg != null) throw new RuntimeException("not null unsigned_short_arg"); + if (int_arg != null) throw new RuntimeException("not null int_arg"); + if (unsigned_int_arg != null) throw new RuntimeException("not null unsigned_int_arg"); + if (long_arg != null) throw new RuntimeException("not null long_arg"); + if (unsigned_long_arg != null) throw new RuntimeException("not null unsigned_long_arg"); + if (long_long_arg != null) throw new RuntimeException("not null long_long_arg"); + // if (unsigned_long_long_arg != null) throw new RuntimeException("not null unsigned_long_long_arg"); + if (float_arg != null) throw new RuntimeException("not null float_arg"); + if (double_arg != null) throw new RuntimeException("not null double_arg"); + } + if (bool_arg != null) bool_arg[0] = true; + if (signed_char_arg != null) signed_char_arg[0] = 12; + if (unsigned_char_arg != null) unsigned_char_arg[0] = 13; + if (short_arg != null) short_arg[0] = 14; + if (unsigned_short_arg != null) unsigned_short_arg[0] = 15; + if (int_arg != null) int_arg[0] = 16; + if (unsigned_int_arg != null) unsigned_int_arg[0] = 17; + if (long_arg != null) long_arg[0] = 18; + if (unsigned_long_arg != null) unsigned_long_arg[0] = 19; + if (long_long_arg != null) long_long_arg[0] = 20; + // if (unsigned_long_long_arg != null) unsigned_long_long_arg[0] = 111; + if (float_arg != null) float_arg[0] = 112; + if (double_arg != null) double_arg[0] = 113; + } +} diff --git a/Examples/test-suite/java/java_director_typemaps_runme.java b/Examples/test-suite/java/java_director_typemaps_runme.java new file mode 100644 index 000000000..a6ab1df39 --- /dev/null +++ b/Examples/test-suite/java/java_director_typemaps_runme.java @@ -0,0 +1,151 @@ +// Test director reference typemaps in typemaps.i - similar to java_director_typemaps_ptr.i testcase + +import java_director_typemaps.*; +import java.math.BigInteger; + +public class java_director_typemaps_runme { + + static { + try { + System.loadLibrary("java_director_typemaps"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + + public static void main(String argv[]) { + Quux quux = new java_director_typemaps_MyQuux(); + quux.etest(); + } +} + +class java_director_typemaps_MyQuux extends Quux { + public java_director_typemaps_MyQuux() { + super(); + } + + public void director_method_output( + boolean[] bool_arg, + + byte[] signed_char_arg, + short[] unsigned_char_arg, + + short[] short_arg, + int[] unsigned_short_arg, + + int[] int_arg, + long[] unsigned_int_arg, + + int[] long_arg, + long[] unsigned_long_arg, + + long[] long_long_arg, + // BigInteger[] unsigned_long_long_arg, + + float[] float_arg, + double[] double_arg) + { + bool_arg[0] = true; + signed_char_arg[0] = 1; + unsigned_char_arg[0] = 2; + short_arg[0] = 3; + unsigned_short_arg[0] = 4; + int_arg[0] = 5; + unsigned_int_arg[0] = 6; + long_arg[0] = 7; + unsigned_long_arg[0] = 8; + long_long_arg[0] = 9; + // unsigned_long_long_arg[0] = 10; + float_arg[0] = 11; + double_arg[0] = 12; + } + + public void director_method_inout( + boolean[] bool_arg, + + byte[] signed_char_arg, + short[] unsigned_char_arg, + + short[] short_arg, + int[] unsigned_short_arg, + + int[] int_arg, + long[] unsigned_int_arg, + + int[] long_arg, + long[] unsigned_long_arg, + + long[] long_long_arg, + // BigInteger[] unsigned_long_long_arg, + + float[] float_arg, + double[] double_arg) + { + if (bool_arg[0]) throw new RuntimeException("unexpected value for bool_arg"); + + if (signed_char_arg[0] != 101) throw new RuntimeException("unexpected value for signed_char_arg"); + if (unsigned_char_arg[0] != 101) throw new RuntimeException("unexpected value for unsigned_char_arg"); + if (short_arg[0] != 101) throw new RuntimeException("unexpected value for short_arg"); + if (unsigned_short_arg[0] != 101) throw new RuntimeException("unexpected value for unsigned_short_arg"); + if (int_arg[0] != 101) throw new RuntimeException("unexpected value for int_arg"); + if (unsigned_int_arg[0] != 101) throw new RuntimeException("unexpected value for unsigned_int_arg"); + if (long_arg[0] != 101) throw new RuntimeException("unexpected value for long_arg"); + if (unsigned_long_arg[0] != 101) throw new RuntimeException("unexpected value for unsigned_long_arg"); + if (long_long_arg[0] != 101) throw new RuntimeException("unexpected value for long_long_arg"); + // if (unsigned_long_long_arg[0] != 101) throw new RuntimeException("unexpected value for unsigned_long_long_arg"); + if (float_arg[0] != 101) throw new RuntimeException("unexpected value for float_arg"); + if (double_arg[0] != 101) throw new RuntimeException("unexpected value for double_arg"); + + bool_arg[0] = false; + signed_char_arg[0] = 11; + unsigned_char_arg[0] = 12; + short_arg[0] = 13; + unsigned_short_arg[0] = 14; + int_arg[0] = 15; + unsigned_int_arg[0] = 16; + long_arg[0] = 17; + unsigned_long_arg[0] = 18; + long_long_arg[0] = 19; + // unsigned_long_long_arg[0] = 110; + float_arg[0] = 111; + double_arg[0] = 112; + } + + public void director_method_nameless_args( + boolean[] bool_arg, + + byte[] signed_char_arg, + short[] unsigned_char_arg, + + short[] short_arg, + int[] unsigned_short_arg, + + int[] int_arg, + long[] unsigned_int_arg, + + int[] long_arg, + long[] unsigned_long_arg, + + long[] long_long_arg, + // BigInteger[] unsigned_long_long_arg, + + float[] float_arg, + double[] double_arg) + { + bool_arg[0] = true; + signed_char_arg[0] = 12; + unsigned_char_arg[0] = 13; + short_arg[0] = 14; + unsigned_short_arg[0] = 15; + int_arg[0] = 16; + unsigned_int_arg[0] = 17; + long_arg[0] = 18; + unsigned_long_arg[0] = 19; + long_long_arg[0] = 20; + // unsigned_long_long_arg[0] = 111; + float_arg[0] = 112; + double_arg[0] = 113; + } +} diff --git a/Examples/test-suite/java/java_enums_runme.java b/Examples/test-suite/java/java_enums_runme.java index bc7d41636..754d391fa 100644 --- a/Examples/test-suite/java/java_enums_runme.java +++ b/Examples/test-suite/java/java_enums_runme.java @@ -13,6 +13,12 @@ public class java_enums_runme implements stuff { public static void main(String argv[]) { + if (WithTrailingComma.Second != 1) + throw new RuntimeException("Incorrect value for Second"); + + if (WithTrailingCommaAndIgnoredFirstItem.SecondNonIgnoredOne != 2) + throw new RuntimeException("Incorrect value for SecondNonIgnoredOne"); + int number = 200; // Switch statement will only compile if these enums are initialised diff --git a/Examples/test-suite/java/java_throws_runme.java b/Examples/test-suite/java/java_throws_runme.java index 0365b69ed..16eab7cad 100644 --- a/Examples/test-suite/java/java_throws_runme.java +++ b/Examples/test-suite/java/java_throws_runme.java @@ -93,6 +93,28 @@ public class java_throws_runme { if (!pass) throw new RuntimeException("Test 6 failed"); + // Interface function + pass = false; + try { + InterfaceTestImpl iti = new InterfaceTestImpl(); + iti.imethod(true); + } + catch (MyException e) { pass = true; } + + if (!pass) + throw new RuntimeException("Test interface 1 failed"); + + pass = false; + try { + InterfaceTestImpl iti = new InterfaceTestImpl(); + iti.imethod(false); + pass = true; + } + catch (MyException e) { pass = false; } + + if (!pass) + throw new RuntimeException("Test interface 2 failed"); + // Global function pass = false; try { diff --git a/Examples/test-suite/java/li_boost_shared_ptr_director_runme.java b/Examples/test-suite/java/li_boost_shared_ptr_director_runme.java new file mode 100644 index 000000000..9349c622b --- /dev/null +++ b/Examples/test-suite/java/li_boost_shared_ptr_director_runme.java @@ -0,0 +1,129 @@ +import li_boost_shared_ptr_director.*; + +public class li_boost_shared_ptr_director_runme { + + static { + try { + System.loadLibrary("li_boost_shared_ptr_director"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + private static void check(int got, int expected) { + if (got != expected) + throw new RuntimeException("Failed, got: " + got + " expected: " + expected); + } + + public static void main(String argv[]) { + li_boost_shared_ptr_director_Derived a = new li_boost_shared_ptr_director_Derived(false); + li_boost_shared_ptr_director_Derived b = new li_boost_shared_ptr_director_Derived(true); + + check(li_boost_shared_ptr_director.call_ret_c_shared_ptr(a), 1); + check(li_boost_shared_ptr_director.call_ret_c_shared_ptr(b), -1); + check(li_boost_shared_ptr_director.call_ret_c_by_value(a), 1); + + check(li_boost_shared_ptr_director.call_ret_c_shared_ptr(a), 1); + check(li_boost_shared_ptr_director.call_ret_c_shared_ptr(b), -1); + check(li_boost_shared_ptr_director.call_ret_c_by_value(a), 1); + + check(li_boost_shared_ptr_director.call_take_c_by_value(a), 5); + check(li_boost_shared_ptr_director.call_take_c_by_ref(a), 6); + check(li_boost_shared_ptr_director.call_take_c_by_pointer(a), 7); + check(li_boost_shared_ptr_director.call_take_c_by_pointer_ref(a), 8); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_value(a), 9); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_ref(a), 10); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_pointer(a), 11); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_pointer_ref(a), 12); + + check(li_boost_shared_ptr_director.call_take_c_by_pointer_with_null(a), -2); + check(li_boost_shared_ptr_director.call_take_c_by_pointer_ref_with_null(a), -3); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_value_with_null(a), -4); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_ref_with_null(a), -5); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_pointer_with_null(a), -6); + check(li_boost_shared_ptr_director.call_take_c_shared_ptr_by_pointer_ref_with_null(a), -7); + } +} + +class li_boost_shared_ptr_director_Derived extends Base { + + private boolean return_none; + + li_boost_shared_ptr_director_Derived(boolean flag) { + super(); + this.return_none = flag; + } + + @Override + public C ret_c_shared_ptr() { + if (this.return_none) + return null; + else + return new C(); + } + + @Override + public C ret_c_by_value() { + return new C(); + } + + @Override + public int take_c_by_value(C c) { + return c.get_m(); + } + + @Override + public int take_c_by_ref(C c) { + return c.get_m(); + } + + @Override + public int take_c_by_pointer(C c) { + if (c != null) + return c.get_m(); + else + return -2; + } + + @Override + public int take_c_by_pointer_ref(C c) { + if (c != null) + return c.get_m(); + else + return -3; + } + + @Override + public int take_c_shared_ptr_by_value(C c) { + if (c != null) + return c.get_m(); + else + return -4; + } + + @Override + public int take_c_shared_ptr_by_ref(C c) { + if (c != null) + return c.get_m(); + else + return -5; + } + + @Override + public int take_c_shared_ptr_by_pointer(C c) { + if (c != null) + return c.get_m(); + else + return -6; + } + + @Override + public int take_c_shared_ptr_by_pointer_ref(C c) { + if (c != null) + return c.get_m(); + else + return -7; + } + +} diff --git a/Examples/test-suite/java/li_std_list_runme.java b/Examples/test-suite/java/li_std_list_runme.java new file mode 100644 index 000000000..96412fdaf --- /dev/null +++ b/Examples/test-suite/java/li_std_list_runme.java @@ -0,0 +1,180 @@ +import li_std_list.*; + +public class li_std_list_runme { + + static { + try { + System.loadLibrary("li_std_list"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) throws Throwable + { + IntList v1 = new IntList(); + DoubleList v2 = new DoubleList(); + + if (!v1.isEmpty()) throw new RuntimeException("v1 test (1) failed"); + if (v1.size() != 0) throw new RuntimeException("v1 test (2) failed"); + if (!v1.add(123)) throw new RuntimeException("v1 test (3) failed"); + if (v1.size() != 1) throw new RuntimeException("v1 test (4) failed"); + if (v1.isEmpty()) throw new RuntimeException("v1 test (5) failed"); + + int sum = 0; + for (int n : v1) { + if (n != 123) throw new RuntimeException("v1 loop test failed"); + sum += n; + } + if (sum != 123) throw new RuntimeException("v1 sum test failed"); + if (v1.get(0) != 123) throw new RuntimeException("v1 test failed"); + v1.clear(); + if (!v1.isEmpty()) throw new RuntimeException("v1 test clear failed"); + v1.add(123); + + if (v1.set(0, 456) != 123) throw new RuntimeException("v1 test (6) failed"); + if (v1.size() != 1) throw new RuntimeException("v1 test (7) failed"); + if (v1.get(0) != 456) throw new RuntimeException("v1 test (8) failed"); + + java.util.Iterator v1_iterator = v1.iterator(); + if (!v1_iterator.hasNext()) throw new RuntimeException("v1 test (9) failed"); + if (v1_iterator.next() != 456) throw new RuntimeException("v1 test (10) failed"); + if (v1_iterator.hasNext()) throw new RuntimeException("v1 test (11) failed"); + try { + v1_iterator.next(); + throw new RuntimeException("v1 test (12) failed"); + } catch (java.util.NoSuchElementException e) { + } + + if (v1.remove(Integer.valueOf(123))) throw new RuntimeException("v1 test (13) failed"); + if (!v1.remove(Integer.valueOf(456))) throw new RuntimeException("v1 test (14) failed"); + if (!v1.isEmpty()) throw new RuntimeException("v1 test (15) failed"); + if (v1.size() != 0) throw new RuntimeException("v1 test (16) failed"); + if (v1.remove(Integer.valueOf(456))) throw new RuntimeException("v1 test (17) failed"); + + if (new IntList(3, 0).size() != 3) throw new RuntimeException("constructor initial size test failed"); + for (int n : new IntList(10, 999)) + if (n != 999) throw new RuntimeException("constructor initialization with value failed"); + for (int n : new IntList(new IntList(10, 999))) + if (n != 999) throw new RuntimeException("copy constructor initialization with value failed"); + + StructList v4 = new StructList(); + StructPtrList v5 = new StructPtrList(); + StructConstPtrList v6 = new StructConstPtrList(); + + v4.add(new Struct(12)); + v5.add(new Struct(34)); + v6.add(new Struct(56)); + + if (v4.get(0).getNum() != 12) throw new RuntimeException("v4 test failed"); + if (v5.get(0).getNum() != 34) throw new RuntimeException("v5 test failed"); + if (v6.get(0).getNum() != 56) throw new RuntimeException("v6 test failed"); + + for (Struct s : v4) { + if (s.getNum() != 12) throw new RuntimeException("v4 loop test failed"); + } + for (Struct s : v5) { + if (s.getNum() != 34) throw new RuntimeException("v5 loop test failed"); + } + for (Struct s : v6) { + if (s.getNum() != 56) throw new RuntimeException("v6 loop test failed"); + } + + StructList v7 = li_std_list.CopyContainerStruct(new StructList()); + v7.add(new Struct(1)); + v7.add(new Struct(23)); + v7.add(new Struct(456)); + v7.add(new Struct(7890)); + if (v7.size() != 4) throw new RuntimeException("v7 test (1) failed"); + { + double[] a7 = {1, 23, 456, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + if (s7.getNum() != a7[i7]) throw new RuntimeException("v7 test (2) failed"); + i7++; + } + if (i7 != a7.length) throw new RuntimeException("v7 test (3) failed"); + } + if (v7.remove(2).getNum() != 456) throw new RuntimeException("v7 test (4) failed"); + { + double[] a7 = {1, 23, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + if (s7.getNum() != a7[i7]) throw new RuntimeException("v7 test (5) failed"); + i7++; + } + if (i7 != a7.length) throw new RuntimeException("v7 test (6) failed"); + } + v7.add(1, new Struct(123)); + { + double[] a7 = {1, 123, 23, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + if (s7.getNum() != a7[i7]) throw new RuntimeException("v7 test (7) failed"); + i7++; + } + if (i7 != a7.length) throw new RuntimeException("v7 test (8) failed"); + } + + BoolList v8 = new BoolList(); + if (!v8.add(true)) throw new RuntimeException("v8 test (1) failed");; + if (v8.get(0) != true) throw new RuntimeException("v8 test (2) failed");; + if (v8.set(0, false) != true) throw new RuntimeException("v8 test (3) failed");; + if (v8.set(0, false) != false) throw new RuntimeException("v8 test (4) failed");; + if (v8.size() != 1) throw new RuntimeException("v8 test (5) failed");; + + java.util.ArrayList bl = new java.util.ArrayList(java.util.Arrays.asList(true, false, true, false)); + BoolList bv = new BoolList(java.util.Arrays.asList(true, false, true, false)); + BoolList bv2 = new BoolList(bl); + java.util.ArrayList bl2 = new java.util.ArrayList(bv); + boolean bbb1 = bv.get(0); + Boolean bbb2 = bv.get(0); + + IntList v9 = new IntList(java.util.Arrays.asList(10, 20, 30, 40)); + v9.add(50); + v9.add(60); + v9.add(70); + if (v9.size() != 7) throw new RuntimeException("v9 test (1) failed"); + if (!v9.remove(Integer.valueOf(60))) throw new RuntimeException("v9 test (2) failed"); + if (v9.size() != 6) throw new RuntimeException("v9 test (3) failed"); + v9.addFirst(-10); + v9.addLast(80); + if (v9.size() != 8) throw new RuntimeException("v9 test (4) failed"); + if (v9.get(0) != -10) throw new RuntimeException("v9 test (5) failed");; + if (v9.get(v9.size()-1) != 80) throw new RuntimeException("v9 test (6) failed");; + v9.removeFirst(); + if (v9.get(0) != 10) throw new RuntimeException("v9 test (7) failed");; + v9.removeLast(); + if (v9.size() != 6) throw new RuntimeException("v9 test (8) failed"); + if (v9.get(v9.size()-1) != 70) throw new RuntimeException("v9 test (9) failed");; + + IntList v10 = new IntList(java.util.Arrays.asList(10, 20, 30, 40, 50)); + v10.subList(1, 4).clear(); // Recommended way to call protected method removeRange(1,3) + if (v10.size() != 2) throw new RuntimeException("v10 test (1) failed"); + if (v10.get(0) != 10) throw new RuntimeException("v10 test (2) failed"); + if (v10.get(1) != 50) throw new RuntimeException("v10 test (3) failed"); + v10.addAll(1, java.util.Arrays.asList(22, 33)); + if (v10.size() != 4) throw new RuntimeException("v10 test (4) failed"); + if (v10.get(1) != 22) throw new RuntimeException("v10 test (5) failed"); + if (v10.get(2) != 33) throw new RuntimeException("v10 test (6) failed"); + + v10.add(v10.size(), 55); + if (v10.size() != 5) throw new RuntimeException("v10 test (7) failed"); + if (v10.get(4) != 55) throw new RuntimeException("v10 test (8) failed"); + + IntList v11 = new IntList(java.util.Arrays.asList(11, 22, 33, 44)); + v11.listIterator(0); + v11.listIterator(v11.size()); + try { + v11.listIterator(v11.size() + 1); + throw new RuntimeException("v11 test (1) failed"); + } catch (IndexOutOfBoundsException e) { + } + try { + v11.listIterator(-1); + throw new RuntimeException("v11 test (2) failed"); + } catch (IndexOutOfBoundsException e) { + } + } +} diff --git a/Examples/test-suite/java/li_std_map_runme.java b/Examples/test-suite/java/li_std_map_runme.java new file mode 100644 index 000000000..7ad4370cc --- /dev/null +++ b/Examples/test-suite/java/li_std_map_runme.java @@ -0,0 +1,122 @@ +import li_std_map.*; + +public class li_std_map_runme { + + static { + try { + System.loadLibrary("li_std_map"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void checkThat(boolean mustBeTrue) throws Throwable { + if (!mustBeTrue) { + // Index [2], since this function is one hop away from main, and [1] is the current method. + throw new RuntimeException("Test failed at line number " + Thread.currentThread().getStackTrace()[2].getLineNumber()); + } + } + + public static void main(String argv[]) throws Throwable + { + java.util.AbstractMap sim = new StringIntMap(); + java.util.AbstractMap iim = new IntIntMap(); + + checkThat(sim.isEmpty()); + checkThat(iim.isEmpty()); + checkThat(sim.size() == 0); + checkThat(iim.size() == 0); + + checkThat(sim.get("key") == null); + checkThat(iim.get(1) == null); + + checkThat(!sim.containsKey("key")); + checkThat(!iim.containsKey(1)); + + checkThat(sim.put("key", 2) == null); + checkThat(iim.put(1, 2) == null); + + checkThat(sim.size() == 1); + checkThat(iim.size() == 1); + checkThat(!sim.isEmpty()); + checkThat(!iim.isEmpty()); + + checkThat(sim.get("key") == 2); + checkThat(iim.get(1) == 2); + + checkThat(sim.remove("key") == 2); + checkThat(iim.remove(1) == 2); + + checkThat(sim.isEmpty()); + checkThat(iim.isEmpty()); + checkThat(sim.size() == 0); + checkThat(iim.size() == 0); + + checkThat(sim.get("key") == null); + checkThat(iim.get(1) == null); + + checkThat(sim.remove("key") == null); + checkThat(iim.remove(1) == null); + + checkThat(sim.put("key", 2) == null); + checkThat(iim.put(1, 2) == null); + + sim.clear(); + iim.clear(); + checkThat(sim.isEmpty()); + checkThat(iim.isEmpty()); + + checkThat(sim.put("key1", 1) == null); + checkThat(iim.put(1, 1) == null); + checkThat(sim.put("key2", 2) == null); + checkThat(iim.put(2, 2) == null); + + checkThat(sim.size() == 2); + checkThat(iim.size() == 2); + checkThat(sim.get("key1") == 1); + checkThat(iim.get(1) == 1); + checkThat(sim.get("key2") == 2); + checkThat(iim.get(2) == 2); + + checkThat(sim.put("key1", 3) == 1); + checkThat(iim.put(1, 3) == 1); + + checkThat(sim.size() == 2); + checkThat(iim.size() == 2); + checkThat(sim.get("key1") == 3); + checkThat(iim.get(1) == 3); + + java.util.Set> sim_es = sim.entrySet(); + java.util.Map sim_default = new java.util.HashMap(); + sim_default.put("key1", 3); + sim_default.put("key2", 2); + java.util.Set> sim_es_default = sim_default.entrySet(); + checkThat(sim_es.size() == sim_es_default.size()); + for (java.util.Map.Entry entry : sim_es) { + checkThat(sim_es_default.contains(entry)); + checkThat(sim_default.containsKey(entry.getKey())); + checkThat(sim_default.containsValue(entry.getValue())); + + Integer oldValue = entry.getValue(); + entry.setValue(oldValue + 1); + checkThat(sim.get(entry.getKey()) == (oldValue + 1)); + } + + java.util.Set> iim_es = iim.entrySet(); + java.util.Map iim_default = new java.util.HashMap(); + iim_default.put(1, 3); + iim_default.put(2, 2); + java.util.Set> iim_es_default = iim_default.entrySet(); + checkThat(iim_es.size() == iim_es_default.size()); + for (java.util.Map.Entry entry : iim_es) { + checkThat(iim_es_default.contains(entry)); + checkThat(iim_default.containsKey(entry.getKey())); + checkThat(iim_default.containsValue(entry.getValue())); + + Integer oldValue = entry.getValue(); + entry.setValue(oldValue + 1); + checkThat(iim.get(entry.getKey()) == (oldValue + 1)); + } + } +} diff --git a/Examples/test-suite/java/li_std_set_runme.java b/Examples/test-suite/java/li_std_set_runme.java new file mode 100644 index 000000000..0e013eba1 --- /dev/null +++ b/Examples/test-suite/java/li_std_set_runme.java @@ -0,0 +1,90 @@ +import li_std_set.*; + +public class li_std_set_runme { + + static { + try { + System.loadLibrary("li_std_set"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void checkThat(boolean mustBeTrue) throws Throwable { + if (!mustBeTrue) { + // Index [2], since this function is one hop away from main, and [1] is the current method. + throw new RuntimeException("Test failed at line number " + Thread.currentThread().getStackTrace()[2].getLineNumber()); + } + } + + public static void main(String argv[]) throws Throwable + { + java.util.AbstractSet ss = new StringSet(); + + checkThat(ss.isEmpty()); + checkThat(!ss.contains("key")); + checkThat(!ss.remove("key")); + + checkThat(ss.add("key")); + checkThat(!ss.add("key")); + checkThat(ss.contains("key")); + checkThat(ss.remove("key")); + checkThat(ss.isEmpty()); + checkThat(ss.size() == 0); + + checkThat(ss.add("key1")); + checkThat(ss.add("key2")); + checkThat(ss.add("key3")); + checkThat(ss.size() == 3); + + ss.clear(); + checkThat(ss.isEmpty()); + checkThat(ss.size() == 0); + + checkThat(ss.addAll(java.util.Arrays.asList("one", "two", "three"))); + checkThat(ss.size() == 3); + checkThat(ss.contains("one")); + checkThat(!ss.contains("four")); + + checkThat(ss.containsAll(java.util.Arrays.asList("one", "two", "three"))); + checkThat(ss.containsAll(java.util.Arrays.asList("one", "two"))); + checkThat(!ss.containsAll(java.util.Arrays.asList("one", "two", "four"))); + checkThat(!ss.containsAll(java.util.Arrays.asList("one", "two", "three", "four"))); + + checkThat(!ss.addAll(java.util.Arrays.asList("one", "two", "three"))); + + java.util.Set found = new java.util.HashSet(); + java.util.Iterator itr = ss.iterator(); + while (itr.hasNext()) { + found.add(itr.next()); + } + + checkThat(ss.containsAll(found)); + checkThat(found.containsAll(ss)); + + java.util.AbstractSet ss2 = new StringSet(ss); + checkThat(ss2.containsAll(ss)); + checkThat(ss.containsAll(ss2)); + + checkThat(!ss.removeAll(java.util.Arrays.asList("five", "four"))); + checkThat(ss.removeAll(found)); + checkThat(ss.isEmpty()); + checkThat(ss.size() == 0); + + // Check a set of another type. + java.util.AbstractSet fooSet = new FooSet(); + checkThat(fooSet.isEmpty()); + checkThat(fooSet.add(new Foo(17))); + checkThat(fooSet.size() == 1); + + // And a set of primitive type. + java.util.AbstractSet intSet = new IntSet(); + checkThat(intSet.isEmpty()); + checkThat(intSet.add(17)); + checkThat(!intSet.add(17)); + checkThat(intSet.size() == 1); + checkThat(intSet.add(289)); + checkThat(intSet.size() == 2); + } +} diff --git a/Examples/test-suite/java/li_std_vector_runme.java b/Examples/test-suite/java/li_std_vector_runme.java index b422655a4..d4c0c95c7 100644 --- a/Examples/test-suite/java/li_std_vector_runme.java +++ b/Examples/test-suite/java/li_std_vector_runme.java @@ -4,21 +4,68 @@ public class li_std_vector_runme { static { try { - System.loadLibrary("li_std_vector"); + System.loadLibrary("li_std_vector"); } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); System.exit(1); } } + public static void checkThat(boolean mustBeTrue) throws Throwable { + if (!mustBeTrue) { + // Index [2], since this function is one hop away from main, and [1] is the current method. + throw new RuntimeException("Test failed at line number " + Thread.currentThread().getStackTrace()[2].getLineNumber()); + } + } + public static void main(String argv[]) throws Throwable { IntVector v1 = li_std_vector.vecintptr(new IntVector()); IntPtrVector v2 = li_std_vector.vecintptr(new IntPtrVector()); IntConstPtrVector v3 = li_std_vector.vecintconstptr(new IntConstPtrVector()); + checkThat(v1.isEmpty()); + checkThat(v1.size() == 0); + checkThat(v1.add(123)); + checkThat(v1.size() == 1); + checkThat(!v1.isEmpty()); + + int sum = 0; + for (int n : v1) { + checkThat(n == 123); + sum += n; + } + checkThat(sum == 123); + checkThat(v1.get(0) == 123); + v1.clear(); + checkThat(v1.isEmpty()); v1.add(123); - if (v1.get(0) != 123) throw new RuntimeException("v1 test failed"); + + checkThat(v1.set(0, 456) == 123); + checkThat(v1.size() == 1); + checkThat(v1.get(0) == 456); + + java.util.Iterator v1_iterator = v1.iterator(); + checkThat(v1_iterator.hasNext()); + checkThat(v1_iterator.next() == 456); + checkThat(!v1_iterator.hasNext()); + try { + v1_iterator.next(); + checkThat(false); + } catch (java.util.NoSuchElementException e) { + } + + checkThat(!v1.remove(Integer.valueOf(123))); + checkThat(v1.remove(Integer.valueOf(456))); + checkThat(v1.isEmpty()); + checkThat(v1.size() == 0); + checkThat(!v1.remove(Integer.valueOf(456))); + + checkThat(new IntVector(3, 0).size() == 3); + for (int n : new IntVector(10, 999)) + checkThat(n == 999); + for (int n : new IntVector(new IntVector(10, 999))) + checkThat(n == 999); StructVector v4 = li_std_vector.vecstruct(new StructVector()); StructPtrVector v5 = li_std_vector.vecstructptr(new StructPtrVector()); @@ -28,9 +75,109 @@ public class li_std_vector_runme { v5.add(new Struct(34)); v6.add(new Struct(56)); - Struct s = null; - if (v4.get(0).getNum() != 12) throw new RuntimeException("v4 test failed"); - if (v5.get(0).getNum() != 34) throw new RuntimeException("v5 test failed"); - if (v6.get(0).getNum() != 56) throw new RuntimeException("v6 test failed"); + checkThat(v4.get(0).getNum() == 12); + checkThat(v5.get(0).getNum() == 34); + checkThat(v6.get(0).getNum() == 56); + + for (Struct s : v4) { + checkThat(s.getNum() == 12); + } + for (Struct s : v5) { + checkThat(s.getNum() == 34); + } + for (Struct s : v6) { + checkThat(s.getNum() == 56); + } + + StructVector v7 = li_std_vector.vecstruct(new StructVector()); + v7.add(new Struct(1)); + v7.add(new Struct(23)); + v7.add(new Struct(456)); + v7.add(new Struct(7890)); + checkThat(v7.size() == 4); + { + double[] a7 = {1, 23, 456, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + checkThat(s7.getNum() == a7[i7]); + i7++; + } + checkThat(i7 == a7.length); + } + checkThat(v7.remove(2).getNum() == 456); + { + double[] a7 = {1, 23, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + checkThat(s7.getNum() == a7[i7]); + i7++; + } + checkThat(i7 == a7.length); + } + v7.add(1, new Struct(123)); + { + double[] a7 = {1, 123, 23, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + checkThat(s7.getNum() == a7[i7]); + i7++; + } + checkThat(i7 == a7.length); + } + + BoolVector v8 = new BoolVector(); + checkThat(v8.add(true)); + checkThat(v8.get(0) == true); + checkThat(v8.set(0, false) == true); + checkThat(v8.set(0, false) == false); + checkThat(v8.size() == 1); + + java.util.ArrayList bl = new java.util.ArrayList(java.util.Arrays.asList(true, false, true, false)); + BoolVector bv = new BoolVector(java.util.Arrays.asList(true, false, true, false)); + BoolVector bv2 = new BoolVector(bl); + java.util.ArrayList bl2 = new java.util.ArrayList(bv); + boolean bbb1 = bv.get(0); + Boolean bbb2 = bv.get(0); + + IntVector v9 = new IntVector(java.util.Arrays.asList(10, 20, 30, 40)); + v9.add(50); + v9.add(60); + v9.add(70); + checkThat(v9.size() == 7); + checkThat(v9.remove(Integer.valueOf(60))); + checkThat(v9.size() == 6); + + IntVector v10 = new IntVector(java.util.Arrays.asList(10, 20, 30, 40, 50)); + v10.subList(1, 4).clear(); // Recommended way to call protected method removeRange(1,3) + checkThat(v10.size() == 2); + checkThat(v10.get(0) == 10); + checkThat(v10.get(1) == 50); + v10.addAll(1, java.util.Arrays.asList(22, 33)); + checkThat(v10.size() == 4); + checkThat(v10.get(1) == 22); + checkThat(v10.get(2) == 33); + + v10.add(v10.size(), 55); + checkThat(v10.size() == 5); + checkThat(v10.get(4) == 55); + + IntVector v11 = new IntVector(java.util.Arrays.asList(11, 22, 33, 44)); + v11.listIterator(0); + v11.listIterator(v11.size()); + try { + v11.listIterator(v11.size() + 1); + checkThat(false); + } catch (IndexOutOfBoundsException e) { + } + try { + v11.listIterator(-1); + checkThat(false); + } catch (IndexOutOfBoundsException e) { + } + + IntVector arrayInit = new IntVector(new int[]{1, 2, 3, 4, 5}); + checkThat(arrayInit.size() == 5); + checkThat(arrayInit.get(0) == 1); + checkThat(arrayInit.get(4) == 5); } } diff --git a/Examples/test-suite/java/long_long_runme.java b/Examples/test-suite/java/long_long_runme.java index 76aa0705d..65a0e79b3 100644 --- a/Examples/test-suite/java/long_long_runme.java +++ b/Examples/test-suite/java/long_long_runme.java @@ -84,14 +84,14 @@ public class long_long_runme { ArrayList bigIntegers = new ArrayList(); for (int i=0; i -%} - %include // DEFINE exceptions in header section using std::runtime_error %{ + #include #include #include @@ -39,7 +32,6 @@ %feature("director:except") MyNS::Foo::ping { jthrowable $error = jenv->ExceptionOccurred(); if ($error) { - jenv->ExceptionClear(); // clear java exception since mapping to c++ exception if (Swig::ExceptionMatches(jenv,$error,"$packagepath/MyJavaException1")) { throw 1; } else if (Swig::ExceptionMatches(jenv,$error,"$packagepath/MyJavaException2")) { @@ -68,7 +60,6 @@ %feature("director:except") MyNS::Foo::pong %{ jthrowable $error = jenv->ExceptionOccurred(); if ($error) { - jenv->ExceptionClear(); $directorthrowshandlers throw ::MyNS::Unexpected(Swig::JavaExceptionMessage(jenv,$error).message()); } @@ -118,7 +109,10 @@ %feature("director:except") MyNS::Foo::genericpong { jthrowable $error = jenv->ExceptionOccurred(); if ($error) { - jenv->ExceptionClear(); + if (Swig::ExceptionMatches(jenv,$error,"UnconstructableException")) { + // Purposefully test NULL + throw Swig::DirectorException(jenv, NULL); + } throw Swig::DirectorException(jenv,$error); } } @@ -128,9 +122,10 @@ %} %feature ("except",throws="Exception") MyNS::Bar::genericpong %{ - try { $action } - catch (Swig::DirectorException & direxcp) { - direxcp.raiseJavaException(jenv); // jenv always available in JNI code + try { + $action + } catch (Swig::DirectorException & direxcp) { + direxcp.throwException(jenv); // jenv always available in JNI code return $null; } %} @@ -170,6 +165,18 @@ namespace MyNS { %catches(MyNS::Exception1,MyNS::Exception2,MyNS::Unexpected) MyNS::Foo::pong; %catches(MyNS::Exception1,MyNS::Exception2,MyNS::Unexpected) MyNS::Bar::pong; +%{ +// throw is deprecated in C++11 and invalid in C++17 and later +#if defined(__cplusplus) && __cplusplus >= 201103L +#define throw(TYPE1, TYPE2) +#else +#define throw(TYPE1, TYPE2) throw(TYPE1, TYPE2) +#if defined(_MSC_VER) + #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif +#endif +%} + %inline %{ namespace MyNS { @@ -182,7 +189,7 @@ public: virtual std::string ping(int excp) throw(int,MyNS::Exception2) = 0; virtual std::string pong(int excp) /* throws MyNS::Exception1 MyNS::Exception2 MyNS::Unexpected) */ = 0; virtual std::string genericpong(int excp) /* unspecified throws - exception is always DirectorException in C++, translated back to whatever thrown in java */ = 0; - virtual std::string directorthrows_warning(int excp) throw(double) { return std::string(); } + virtual std::string directorthrows_warning(int excp) throw(int,double) { return std::string(); } }; // Make a bar from a foo, so a call to Java Bar diff --git a/Examples/test-suite/java_director_exception_feature_nspace.i b/Examples/test-suite/java_director_exception_feature_nspace.i index 264c2a938..b52c1acf4 100644 --- a/Examples/test-suite/java_director_exception_feature_nspace.i +++ b/Examples/test-suite/java_director_exception_feature_nspace.i @@ -11,18 +11,11 @@ #define PACKAGESLASH "java_director_exception_feature_nspacePackage/" %} -%{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - -#include -%} - %include // DEFINE exceptions in header section using std::runtime_error %{ + #include #include #include @@ -46,7 +39,6 @@ %feature("director:except") MyNS::Foo::ping { jthrowable $error = jenv->ExceptionOccurred(); if ($error) { - jenv->ExceptionClear(); // clear java exception since mapping to c++ exception if (Swig::ExceptionMatches(jenv,$error,"$packagepath/MyNS/MyJavaException1")) { throw 1; } else if (Swig::ExceptionMatches(jenv,$error,"$packagepath/MyNS/MyJavaException2")) { @@ -75,7 +67,6 @@ %feature("director:except") MyNS::Foo::pong %{ jthrowable $error = jenv->ExceptionOccurred(); if ($error) { - jenv->ExceptionClear(); $directorthrowshandlers throw ::MyNS::Unexpected(Swig::JavaExceptionMessage(jenv,$error).message()); } @@ -125,7 +116,10 @@ %feature("director:except") MyNS::Foo::genericpong { jthrowable $error = jenv->ExceptionOccurred(); if ($error) { - jenv->ExceptionClear(); + if (Swig::ExceptionMatches(jenv,$error,"java_director_exception_feature_nspace_UnconstructibleException")) { + // Purposefully test NULL + throw Swig::DirectorException(jenv, NULL); + } throw Swig::DirectorException(jenv,$error); } } @@ -135,9 +129,10 @@ %} %feature ("except",throws="Exception") MyNS::Bar::genericpong %{ - try { $action } - catch (Swig::DirectorException & direxcp) { - direxcp.raiseJavaException(jenv); // jenv always available in JNI code + try { + $action + } catch (Swig::DirectorException & direxcp) { + direxcp.throwException(jenv); // jenv always available in JNI code return $null; } %} @@ -177,6 +172,18 @@ namespace MyNS { %catches(MyNS::Exception1,MyNS::Exception2,MyNS::Unexpected) MyNS::Foo::pong; %catches(MyNS::Exception1,MyNS::Exception2,MyNS::Unexpected) MyNS::Bar::pong; +%{ +// throw is deprecated in C++11 and invalid in C++17 and later +#if defined(__cplusplus) && __cplusplus >= 201103L +#define throw(TYPE1, TYPE2) +#else +#define throw(TYPE1, TYPE2) throw(TYPE1, TYPE2) +#if defined(_MSC_VER) + #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif +#endif +%} + %inline %{ namespace MyNS { diff --git a/Examples/test-suite/java_director_typemaps.i b/Examples/test-suite/java_director_typemaps.i new file mode 100644 index 000000000..2ffdeae89 --- /dev/null +++ b/Examples/test-suite/java_director_typemaps.i @@ -0,0 +1,368 @@ +%module(directors="1") java_director_typemaps +// Test director reference typemaps in typemaps.i - similar to java_director_typemaps_ptr.i testcase + +%feature("director", assumeoverride=1) Quux; + +%include + +%apply bool& OUTPUT {bool&}; + +%apply signed char& OUTPUT {signed char&}; +%apply unsigned char& OUTPUT {unsigned char&}; + +%apply short& OUTPUT {short&}; +%apply unsigned short& OUTPUT {unsigned short&}; + +%apply int& OUTPUT {int&}; +%apply unsigned int& OUTPUT {unsigned int&}; + +%apply long& OUTPUT {long&}; +%apply unsigned long& OUTPUT {unsigned long&}; + +%apply long long& OUTPUT {long long&}; +// %apply unsigned long long& OUTPUT {unsigned long long&}; + +%apply float& OUTPUT {float&}; +%apply double& OUTPUT {double&}; + +%apply bool& OUTPUT {bool& boolarg_output}; + +%apply signed char& OUTPUT {signed char& signed_chararg_output}; +%apply unsigned char& OUTPUT {unsigned char& unsigned_chararg_output}; + +%apply short& OUTPUT {short& shortarg_output}; +%apply unsigned short& OUTPUT {unsigned short& unsigned_shortarg_output}; + +%apply int& OUTPUT {int& intarg_output}; +%apply unsigned int& OUTPUT {unsigned int& unsigned_intarg_output}; + +%apply long& OUTPUT {long& longarg_output}; +%apply unsigned long& OUTPUT {unsigned long& unsigned_longarg_output}; + +%apply long long& OUTPUT {long long& long_longarg_output}; +// %apply unsigned long long& OUTPUT {unsigned long long& unsigned_long_longarg_output}; + +%apply float& OUTPUT {float& floatarg_output}; +%apply double& OUTPUT {double& doublearg_output}; + +%apply bool& INOUT {bool& boolarg_inout}; + +%apply signed char& INOUT {signed char& signed_chararg_inout}; +%apply unsigned char& INOUT {unsigned char& unsigned_chararg_inout}; + +%apply short& INOUT {short& shortarg_inout}; +%apply unsigned short& INOUT {unsigned short& unsigned_shortarg_inout}; + +%apply int& INOUT {int& intarg_inout}; +%apply unsigned int& INOUT {unsigned int& unsigned_intarg_inout}; + +%apply long& INOUT {long& longarg_inout}; +%apply unsigned long& INOUT {unsigned long& unsigned_longarg_inout}; + +%apply long long& INOUT {long long& long_longarg_inout}; +// %apply unsigned long long& INOUT {unsigned long long& unsigned_long_longarg_inout}; + +%apply float& INOUT {float& floatarg_inout}; +%apply double& INOUT {double& doublearg_inout}; + +%{ +#include +#define verify(ok) if (!(ok)) throw std::runtime_error(# ok); +%} +%inline %{ + +class Quux { +public: + Quux() {} + virtual ~Quux() {} + + virtual void director_method_output( + bool& boolarg_output, + + signed char& signed_chararg_output, + unsigned char& unsigned_chararg_output, + + short& shortarg_output, + unsigned short& unsigned_shortarg_output, + + int& intarg_output, + unsigned int& unsigned_intarg_output, + + long& longarg_output, + unsigned long& unsigned_longarg_output, + + long long& long_longarg_output, + // unsigned long long& unsigned_long_longarg_output, + + float& floatarg_output, + double& doublearg_output) + { + boolarg_output = false; + + signed_chararg_output = 50; + unsigned_chararg_output = 50; + + shortarg_output = 50; + unsigned_shortarg_output = 50; + + intarg_output = 50; + unsigned_intarg_output = 50; + + longarg_output = 50; + unsigned_longarg_output = 50; + + long_longarg_output = 50; + // unsigned_long_longarg_output = 50; + + floatarg_output = 50; + doublearg_output = 50; + } + + virtual void director_method_inout( + bool& boolarg_inout, + + signed char& signed_chararg_inout, + unsigned char& unsigned_chararg_inout, + + short& shortarg_inout, + unsigned short& unsigned_shortarg_inout, + + int& intarg_inout, + unsigned int& unsigned_intarg_inout, + + long& longarg_inout, + unsigned long& unsigned_longarg_inout, + + long long& long_longarg_inout, + // unsigned long long& unsigned_long_longarg_inout, + + float& floatarg_inout, + double& doublearg_inout) + { + boolarg_inout = false; + + signed_chararg_inout = 50; + unsigned_chararg_inout = 50; + + shortarg_inout = 50; + unsigned_shortarg_inout = 50; + + intarg_inout = 50; + unsigned_intarg_inout = 50; + + longarg_inout = 50; + unsigned_longarg_inout = 50; + + long_longarg_inout = 50; + // unsigned_long_longarg_inout = 50; + + floatarg_inout = 50; + doublearg_inout = 50; + } + + virtual void director_method_nameless_args( + bool& , + + signed char& , + unsigned char& , + + short& , + unsigned short& , + + int& , + unsigned int& , + + long& , + unsigned long& , + + long long& , + // unsigned long long& , + + float& , + double&) + { + } + + void etest() { + bool boolarg_inout = false; + + signed char signed_chararg_inout = 111; + unsigned char unsigned_chararg_inout = 150; + + short shortarg_inout = 150; + unsigned short unsigned_shortarg_inout = 150; + + int intarg_inout = 150; + unsigned int unsigned_intarg_inout = 150; + + long longarg_inout = 150; + unsigned long unsigned_longarg_inout = 150; + + long long long_longarg_inout = 150; + // unsigned long long unsigned_long_longarg_inout = 150; + + float floatarg_inout = 150; + double doublearg_inout = 150; + + director_method_output( + boolarg_inout, + + signed_chararg_inout, + unsigned_chararg_inout, + + shortarg_inout, + unsigned_shortarg_inout, + + intarg_inout, + unsigned_intarg_inout, + + longarg_inout, + unsigned_longarg_inout, + + long_longarg_inout, + // unsigned_long_longarg_inout, + + floatarg_inout, + doublearg_inout); + + verify(boolarg_inout == true); + verify(signed_chararg_inout == 1); + verify(unsigned_chararg_inout == 2); + + verify(shortarg_inout == 3); + verify(unsigned_shortarg_inout == 4); + + verify(intarg_inout == 5); + verify(unsigned_intarg_inout == 6); + + verify(longarg_inout == 7); + verify(unsigned_longarg_inout == 8); + + verify(long_longarg_inout == 9); + // verify(unsigned_long_longarg_inout == 10); + + verify(floatarg_inout == 11); + verify(doublearg_inout == 12); + + boolarg_inout = false; + + signed_chararg_inout = 101; + unsigned_chararg_inout = 101; + + shortarg_inout = 101; + unsigned_shortarg_inout = 101; + + intarg_inout = 101; + unsigned_intarg_inout = 101; + + longarg_inout = 101; + unsigned_longarg_inout = 101; + + long_longarg_inout = 101; + // unsigned_long_longarg_inout = 101; + + floatarg_inout = 101; + doublearg_inout = 101; + + director_method_inout( + boolarg_inout, + + signed_chararg_inout, + unsigned_chararg_inout, + + shortarg_inout, + unsigned_shortarg_inout, + + intarg_inout, + unsigned_intarg_inout, + + longarg_inout, + unsigned_longarg_inout, + + long_longarg_inout, + // unsigned_long_longarg_inout, + + floatarg_inout, + doublearg_inout); + + verify(boolarg_inout == false); + verify(signed_chararg_inout == 11); + verify(unsigned_chararg_inout == 12); + + verify(shortarg_inout == 13); + verify(unsigned_shortarg_inout == 14); + + verify(intarg_inout == 15); + verify(unsigned_intarg_inout == 16); + + verify(longarg_inout == 17); + verify(unsigned_longarg_inout == 18); + + verify(long_longarg_inout == 19); + // verify(unsigned_long_longarg_inout == 110); + + verify(floatarg_inout == 111); + verify(doublearg_inout == 112); + + director_method_nameless_args( + boolarg_inout, + + signed_chararg_inout, + unsigned_chararg_inout, + + shortarg_inout, + unsigned_shortarg_inout, + + intarg_inout, + unsigned_intarg_inout, + + longarg_inout, + unsigned_longarg_inout, + + long_longarg_inout, + // unsigned_long_longarg_inout, + + floatarg_inout, + doublearg_inout); + + verify(boolarg_inout == true); + verify(signed_chararg_inout == 12); + verify(unsigned_chararg_inout == 13); + + verify(shortarg_inout == 14); + verify(unsigned_shortarg_inout == 15); + + verify(intarg_inout == 16); + verify(unsigned_intarg_inout == 17); + + verify(longarg_inout == 18); + verify(unsigned_longarg_inout == 19); + + verify(long_longarg_inout == 20); + // verify(unsigned_long_longarg_inout == 111); + + verify(floatarg_inout == 112); + verify(doublearg_inout == 113); + } +}; +%} + +%clear bool&; + +%clear signed char&; +%clear unsigned char&; + +%clear short&; +%clear unsigned short&; + +%clear int&; +%clear unsigned int&; + +%clear long&; +%clear unsigned long&; + +%clear long long&; +// %clear unsigned long long&; + +%clear float&; +%clear double&; diff --git a/Examples/test-suite/java_director_typemaps_ptr.i b/Examples/test-suite/java_director_typemaps_ptr.i new file mode 100644 index 000000000..578001ac1 --- /dev/null +++ b/Examples/test-suite/java_director_typemaps_ptr.i @@ -0,0 +1,433 @@ +%module(directors="1") java_director_typemaps +// Test director pointer typemaps in typemaps.i - similar to java_director_typemaps.i testcase + +%feature("director", assumeoverride=1) Quux; + +%include + +%apply bool* OUTPUT {bool*}; + +%apply signed char* OUTPUT {signed char*}; +%apply unsigned char* OUTPUT {unsigned char*}; + +%apply short* OUTPUT {short*}; +%apply unsigned short* OUTPUT {unsigned short*}; + +%apply int* OUTPUT {int*}; +%apply unsigned int* OUTPUT {unsigned int*}; + +%apply long* OUTPUT {long*}; +%apply unsigned long* OUTPUT {unsigned long*}; + +%apply long long* OUTPUT {long long*}; +// %apply unsigned long long* OUTPUT {unsigned long long*}; + +%apply float* OUTPUT {float*}; +%apply double* OUTPUT {double*}; + +%apply bool* OUTPUT {bool* boolarg_output}; + +%apply signed char* OUTPUT {signed char* signed_chararg_output}; +%apply unsigned char* OUTPUT {unsigned char* unsigned_chararg_output}; + +%apply short* OUTPUT {short* shortarg_output}; +%apply unsigned short* OUTPUT {unsigned short* unsigned_shortarg_output}; + +%apply int* OUTPUT {int* intarg_output}; +%apply unsigned int* OUTPUT {unsigned int* unsigned_intarg_output}; + +%apply long* OUTPUT {long* longarg_output}; +%apply unsigned long* OUTPUT {unsigned long* unsigned_longarg_output}; + +%apply long long* OUTPUT {long long* long_longarg_output}; +// %apply unsigned long long* OUTPUT {unsigned long long* unsigned_long_longarg_output}; + +%apply float* OUTPUT {float* floatarg_output}; +%apply double* OUTPUT {double* doublearg_output}; + +%apply bool* INOUT {bool* boolarg_inout}; + +%apply signed char* INOUT {signed char* signed_chararg_inout}; +%apply unsigned char* INOUT {unsigned char* unsigned_chararg_inout}; + +%apply short* INOUT {short* shortarg_inout}; +%apply unsigned short* INOUT {unsigned short* unsigned_shortarg_inout}; + +%apply int* INOUT {int* intarg_inout}; +%apply unsigned int* INOUT {unsigned int* unsigned_intarg_inout}; + +%apply long* INOUT {long* longarg_inout}; +%apply unsigned long* INOUT {unsigned long* unsigned_longarg_inout}; + +%apply long long* INOUT {long long* long_longarg_inout}; +// %apply unsigned long long* INOUT {unsigned long long* unsigned_long_longarg_inout}; + +%apply float* INOUT {float* floatarg_inout}; +%apply double* INOUT {double* doublearg_inout}; + +%{ +#include +#define verify(ok) if (!(ok)) throw std::runtime_error(# ok); +%} +%inline %{ + +class Quux { +public: + Quux() {} + virtual ~Quux() {} + + virtual void director_method_output( + bool* boolarg_output, + + signed char* signed_chararg_output, + unsigned char* unsigned_chararg_output, + + short* shortarg_output, + unsigned short* unsigned_shortarg_output, + + int* intarg_output, + unsigned int* unsigned_intarg_output, + + long* longarg_output, + unsigned long* unsigned_longarg_output, + + long long* long_longarg_output, + // unsigned long long* unsigned_long_longarg_output, + + float* floatarg_output, + double* doublearg_output) + { + if (boolarg_output) *boolarg_output = false; + + if (signed_chararg_output) *signed_chararg_output = 50; + if (unsigned_chararg_output) *unsigned_chararg_output = 50; + + if (shortarg_output) *shortarg_output = 50; + if (unsigned_shortarg_output) *unsigned_shortarg_output = 50; + + if (intarg_output) *intarg_output = 50; + if (unsigned_intarg_output) *unsigned_intarg_output = 50; + + if (longarg_output) *longarg_output = 50; + if (unsigned_longarg_output) *unsigned_longarg_output = 50; + + if (long_longarg_output) *long_longarg_output = 50; + // if (unsigned_long_longarg_output) *unsigned_long_longarg_output = 50; + + if (floatarg_output) *floatarg_output = 50; + if (doublearg_output) *doublearg_output = 50; + } + + virtual void director_method_inout( + bool* boolarg_inout, + + signed char* signed_chararg_inout, + unsigned char* unsigned_chararg_inout, + + short* shortarg_inout, + unsigned short* unsigned_shortarg_inout, + + int* intarg_inout, + unsigned int* unsigned_intarg_inout, + + long* longarg_inout, + unsigned long* unsigned_longarg_inout, + + long long* long_longarg_inout, + // unsigned long long* unsigned_long_longarg_inout, + + float* floatarg_inout, + double* doublearg_inout) + { + if (boolarg_inout) *boolarg_inout = false; + + if (signed_chararg_inout) *signed_chararg_inout = 50; + if (unsigned_chararg_inout) *unsigned_chararg_inout = 50; + + if (shortarg_inout) *shortarg_inout = 50; + if (unsigned_shortarg_inout) *unsigned_shortarg_inout = 50; + + if (intarg_inout) *intarg_inout = 50; + if (unsigned_intarg_inout) *unsigned_intarg_inout = 50; + + if (longarg_inout) *longarg_inout = 50; + if (unsigned_longarg_inout) *unsigned_longarg_inout = 50; + + if (long_longarg_inout) *long_longarg_inout = 50; + // if (unsigned_long_longarg_inout) *unsigned_long_longarg_inout = 50; + + if (floatarg_inout) *floatarg_inout = 50; + if (doublearg_inout) *doublearg_inout = 50; + } + + virtual void director_method_nameless_args( + bool* , + + signed char* , + unsigned char* , + + short* , + unsigned short* , + + int* , + unsigned int* , + + long* , + unsigned long* , + + long long* , + // unsigned long long* , + + float* , + double*) + { + } + + void etest() { + bool boolarg_inout = false; + + signed char signed_chararg_inout = 111; + unsigned char unsigned_chararg_inout = 150; + + short shortarg_inout = 150; + unsigned short unsigned_shortarg_inout = 150; + + int intarg_inout = 150; + unsigned int unsigned_intarg_inout = 150; + + long longarg_inout = 150; + unsigned long unsigned_longarg_inout = 150; + + long long long_longarg_inout = 150; + // unsigned long long unsigned_long_longarg_inout = 150; + + float floatarg_inout = 150; + double doublearg_inout = 150; + + director_method_output( + &boolarg_inout, + + &signed_chararg_inout, + &unsigned_chararg_inout, + + &shortarg_inout, + &unsigned_shortarg_inout, + + &intarg_inout, + &unsigned_intarg_inout, + + &longarg_inout, + &unsigned_longarg_inout, + + &long_longarg_inout, + // &unsigned_long_longarg_inout, + + &floatarg_inout, + &doublearg_inout); + + verify(boolarg_inout == true); + verify(signed_chararg_inout == 1); + verify(unsigned_chararg_inout == 2); + + verify(shortarg_inout == 3); + verify(unsigned_shortarg_inout == 4); + + verify(intarg_inout == 5); + verify(unsigned_intarg_inout == 6); + + verify(longarg_inout == 7); + verify(unsigned_longarg_inout == 8); + + verify(long_longarg_inout == 9); + // verify(unsigned_long_longarg_inout == 10); + + verify(floatarg_inout == 11); + verify(doublearg_inout == 12); + + boolarg_inout = false; + + signed_chararg_inout = 101; + unsigned_chararg_inout = 101; + + shortarg_inout = 101; + unsigned_shortarg_inout = 101; + + intarg_inout = 101; + unsigned_intarg_inout = 101; + + longarg_inout = 101; + unsigned_longarg_inout = 101; + + long_longarg_inout = 101; + // unsigned_long_longarg_inout = 101; + + floatarg_inout = 101; + doublearg_inout = 101; + + director_method_inout( + &boolarg_inout, + + &signed_chararg_inout, + &unsigned_chararg_inout, + + &shortarg_inout, + &unsigned_shortarg_inout, + + &intarg_inout, + &unsigned_intarg_inout, + + &longarg_inout, + &unsigned_longarg_inout, + + &long_longarg_inout, + // &unsigned_long_longarg_inout, + + &floatarg_inout, + &doublearg_inout); + + verify(boolarg_inout == false); + verify(signed_chararg_inout == 11); + verify(unsigned_chararg_inout == 12); + + verify(shortarg_inout == 13); + verify(unsigned_shortarg_inout == 14); + + verify(intarg_inout == 15); + verify(unsigned_intarg_inout == 16); + + verify(longarg_inout == 17); + verify(unsigned_longarg_inout == 18); + + verify(long_longarg_inout == 19); + // verify(unsigned_long_longarg_inout == 110); + + verify(floatarg_inout == 111); + verify(doublearg_inout == 112); + + director_method_nameless_args( + &boolarg_inout, + + &signed_chararg_inout, + &unsigned_chararg_inout, + + &shortarg_inout, + &unsigned_shortarg_inout, + + &intarg_inout, + &unsigned_intarg_inout, + + &longarg_inout, + &unsigned_longarg_inout, + + &long_longarg_inout, + // &unsigned_long_longarg_inout, + + &floatarg_inout, + &doublearg_inout); + + verify(boolarg_inout == true); + verify(signed_chararg_inout == 12); + verify(unsigned_chararg_inout == 13); + + verify(shortarg_inout == 14); + verify(unsigned_shortarg_inout == 15); + + verify(intarg_inout == 16); + verify(unsigned_intarg_inout == 17); + + verify(longarg_inout == 18); + verify(unsigned_longarg_inout == 19); + + verify(long_longarg_inout == 20); + // verify(unsigned_long_longarg_inout == 111); + + verify(floatarg_inout == 112); + verify(doublearg_inout == 113); + } + + void nulltest() { + director_method_output( + NULL, + + NULL, + NULL, + + NULL, + NULL, + + NULL, + NULL, + + NULL, + NULL, + + NULL, + // NULL, + + NULL, + NULL); + + director_method_inout( + NULL, + + NULL, + NULL, + + NULL, + NULL, + + NULL, + NULL, + + NULL, + NULL, + + NULL, + // NULL, + + NULL, + NULL); + + director_method_nameless_args( + NULL, + + NULL, + NULL, + + NULL, + NULL, + + NULL, + NULL, + + NULL, + NULL, + + NULL, + // NULL, + + NULL, + NULL); + } +}; +%} + +%clear bool*; + +%clear signed char*; +%clear unsigned char*; + +%clear short*; +%clear unsigned short*; + +%clear int*; +%clear unsigned int*; + +%clear long*; +%clear unsigned long*; + +%clear long long*; +// %clear unsigned long long*; + +%clear float*; +%clear double*; diff --git a/Examples/test-suite/java_enums.i b/Examples/test-suite/java_enums.i index 855913d06..cad492652 100644 --- a/Examples/test-suite/java_enums.i +++ b/Examples/test-suite/java_enums.i @@ -18,6 +18,21 @@ import java.io.*; // For Serializable // Set default Java const code generation %javaconst(1); +// Test enums with trailing comma after the last item. +enum WithTrailingComma +{ + First, + Second, +}; + +%ignore ReallyFirstOneIsIgnored; +enum WithTrailingCommaAndIgnoredFirstItem +{ + ReallyFirstOneIsIgnored, + FirstNonIgnoredOne, + SecondNonIgnoredOne, +}; + // Change the default generation so that these enums are generated into an interface instead of a class %typemap(javaclassmodifiers) enum stuff "public interface" diff --git a/Examples/test-suite/java_throws.i b/Examples/test-suite/java_throws.i index 48a0eeabc..6cd47b448 100644 --- a/Examples/test-suite/java_throws.i +++ b/Examples/test-suite/java_throws.i @@ -2,6 +2,12 @@ %module java_throws +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) +%{ +#define TESTCASE_THROW1(T1) +%} + // Exceptions are chosen at random but are ones which have to have a try catch block to compile %typemap(in, throws=" ClassNotFoundException") int num { $1 = (int)$input; @@ -39,13 +45,7 @@ short full_of_exceptions(int num) { return $null; } %inline %{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif -bool throw_spec_function(int value) throw (int) { throw (int)0; } -#if defined(_MSC_VER) - #pragma warning(default: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +bool throw_spec_function(int value) TESTCASE_THROW1(int) { throw (int)0; } %} %catches(int) catches_function(int value); @@ -126,6 +126,24 @@ JAVAEXCEPTION(FeatureTest::staticMethod) }; %} +%include +%interface_impl(InterfaceTest); +JAVAEXCEPTION(imethod) + +%inline %{ + struct InterfaceTest { + virtual void imethod(bool raise) = 0; + virtual ~InterfaceTest() {} + }; + + struct InterfaceTestImpl : InterfaceTest { + void imethod(bool raise) { + if (raise) + throw MyException("raise message"); + } + }; +%} + // Mixing except feature and typemaps when both generate a class for the throws clause %typemap(in, throws="ClassNotFoundException") int both { $1 = (int)$input; @@ -165,6 +183,7 @@ try { // Need to handle the checked exception in NoExceptTest.delete() %typemap(javafinalize) SWIGTYPE %{ + @SuppressWarnings("deprecation") protected void finalize() { try { delete(); diff --git a/Examples/test-suite/javascript/Makefile.in b/Examples/test-suite/javascript/Makefile.in index b430f236f..8127415f1 100644 --- a/Examples/test-suite/javascript/Makefile.in +++ b/Examples/test-suite/javascript/Makefile.in @@ -66,14 +66,14 @@ ifeq (node,$(JSENGINE)) $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ SWIGOPT='-javascript $(SWIGOPT) -o $*_wrap.cxx $(srcdir)/../$*.i' swiginvoke && \ - $(COMPILETOOL) $(NODEGYP) --loglevel=silent --directory $* configure build 1>>/dev/null + MAKEFLAGS= $(COMPILETOOL) $(NODEGYP) --loglevel=silent --directory $* configure build 1>>/dev/null swig_and_compile_cpp = \ $(setup_node) && \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ SWIGOPT='-c++ -javascript $(SWIGOPT) $(srcdir)/../$*.i' swiginvoke && \ - $(COMPILETOOL) $(NODEGYP) --loglevel=silent --directory $* configure build 1>>/dev/null + MAKEFLAGS= $(COMPILETOOL) $(NODEGYP) --loglevel=silent --directory $* configure build 1>>/dev/null run_testcase = \ if [ -f $(srcdir)/$*$(SCRIPTSUFFIX) ]; then \ @@ -83,12 +83,12 @@ ifeq (node,$(JSENGINE)) %.ctest: $(_setup) - $(swig_and_compile_c) + +$(swig_and_compile_c) $(run_testcase) %.cpptest: $(_setup) - $(swig_and_compile_cpp) + +$(swig_and_compile_cpp) $(run_testcase) %.multicpptest: diff --git a/Examples/test-suite/javascript/complextest_runme.js b/Examples/test-suite/javascript/complextest_runme.js index b87d6bffa..1d9825f3b 100644 --- a/Examples/test-suite/javascript/complextest_runme.js +++ b/Examples/test-suite/javascript/complextest_runme.js @@ -8,8 +8,16 @@ a_c = complextest.Conj(a); if (a_c.toString() != expected.toString()) throw "Error in Conj(a)"; -a_c_f = complextest.Conjf(a); -if (a_c_f.toString() != expected.toString()) +a_c = complextest.Conjf(a); +if (a_c.toString() != expected.toString()) + throw "Error in Conjf(a)"; + +a_c = complextest.Conj2(a); +if (a_c.toString() != expected.toString()) + throw "Error in Conj(a)"; + +a_c = complextest.Conjf2(a); +if (a_c.toString() != expected.toString()) throw "Error in Conjf(a)"; v = new complextest.VectorStdCplx(); @@ -19,4 +27,5 @@ v.add([4,3]); v.add(1); // TODO: how to check validity? -complextest.Copy_h(v); +complextest.CopyHalf(v); +complextest.CopyHalfRef(v); diff --git a/Examples/test-suite/javascript/null_pointer_runme.js b/Examples/test-suite/javascript/null_pointer_runme.js index 7c0d61244..8a9b61186 100644 --- a/Examples/test-suite/javascript/null_pointer_runme.js +++ b/Examples/test-suite/javascript/null_pointer_runme.js @@ -1,6 +1,6 @@ var null_pointer = require("null_pointer"); -if (!null_pointer.func(null)) { +if (!null_pointer.funk(null)) { throw new Error("Javascript 'null' should be converted into NULL."); } diff --git a/Examples/test-suite/javascript/overload_null_runme.js b/Examples/test-suite/javascript/overload_null_runme.js new file mode 100644 index 000000000..f1e35cac7 --- /dev/null +++ b/Examples/test-suite/javascript/overload_null_runme.js @@ -0,0 +1,49 @@ +// There are no typecheck typemaps in Javascript yet, so most of this test +// does not actually worked - the check functions have thus been commented out. +var overload_null = require("overload_null"); + +var check = function(expected, actual) { + if (expected !== actual) { + throw new Error(a + " does not equal " + b); + } +}; + + +var o = new overload_null.Overload(); +var x = new overload_null.X(); + +check(1, o.byval1(x)); +// check(2, o.byval1(null)); + +// check(3, o.byval2(null)); +check(4, o.byval2(x)); + +check(5, o.byref1(x)); +// check(6, o.byref1(null)); + +// check(7, o.byref2(null)); +check(8, o.byref2(x)); + +check(9, o.byconstref1(x)); +// check(10, o.byconstref1(null)); + +// check(11, o.byconstref2(null)); +check(12, o.byconstref2(x)); + +// const pointer references +check(13, o.byval1cpr(x)); +// check(14, o.byval1cpr(null)); + +// check(15, o.byval2cpr(null)); +check(16, o.byval2cpr(x)); + +// forward class declaration +check(17, o.byval1forwardptr(x)); +// check(18, o.byval1forwardptr(null)); + +// check(19, o.byval2forwardptr(null)); +check(20, o.byval2forwardptr(x)); + +check(21, o.byval1forwardref(x)); + +check(22, o.byval2forwardref(x)); diff --git a/Examples/test-suite/javascript/rename1_runme.js b/Examples/test-suite/javascript/rename1_runme.js index 68ecc11b6..7b2ac37b6 100644 --- a/Examples/test-suite/javascript/rename1_runme.js +++ b/Examples/test-suite/javascript/rename1_runme.js @@ -10,7 +10,6 @@ function part1() { xyz.tMethod2(0); xyz.tMethodNotXYZ2(notxyz); xyz.opNotXYZ2(); - xyz.opXYZ2(); } function part2() { @@ -23,7 +22,6 @@ function part2() { xyz.tMethod1(0); xyz.tMethodNotXYZ1(notxyz); xyz.opNotXYZ1(); - xyz.opXYZ1(); } function part3(){ @@ -36,7 +34,6 @@ function part3(){ xyz.tMethod3(new rename.Klass()); xyz.tMethodNotXYZ3(notxyz); xyz.opNotXYZ3(); - xyz.opXYZ3(); } function part4() { @@ -49,7 +46,6 @@ function part4() { xyz.tMethod4(rename.En1); xyz.tMethodNotXYZ4(notxyz); xyz.opNotXYZ4(); - xyz.opXYZ4(); } function part5() { diff --git a/Examples/test-suite/javascript/rename2_runme.js b/Examples/test-suite/javascript/rename2_runme.js index 99f478596..040c798bb 100644 --- a/Examples/test-suite/javascript/rename2_runme.js +++ b/Examples/test-suite/javascript/rename2_runme.js @@ -10,7 +10,6 @@ function part1() { xyz.tMethod2(0); xyz.tMethodNotXYZ2(notxyz); xyz.opNotXYZ2(); - xyz.opXYZ2(); } function part2() { @@ -23,7 +22,6 @@ function part2() { xyz.tMethod1(0); xyz.tMethodNotXYZ1(notxyz); xyz.opNotXYZ1(); - xyz.opXYZ1(); } function part3(){ @@ -36,7 +34,6 @@ function part3(){ xyz.tMethod3(new rename.Klass()); xyz.tMethodNotXYZ3(notxyz); xyz.opNotXYZ3(); - xyz.opXYZ3(); } function part4() { @@ -49,7 +46,6 @@ function part4() { xyz.tMethod4(rename.En1); xyz.tMethodNotXYZ4(notxyz); xyz.opNotXYZ4(); - xyz.opXYZ4(); } function part5() { diff --git a/Examples/test-suite/javascript/rename3_runme.js b/Examples/test-suite/javascript/rename3_runme.js index 237029fbb..fb9393b03 100644 --- a/Examples/test-suite/javascript/rename3_runme.js +++ b/Examples/test-suite/javascript/rename3_runme.js @@ -10,7 +10,6 @@ function part1() { xyz.tMethod2(0); xyz.tMethodNotXYZ2(notxyz); xyz.opNotXYZ2(); - xyz.opXYZ2(); } function part2() { @@ -23,7 +22,6 @@ function part2() { xyz.tMethod1(0); xyz.tMethodNotXYZ1(notxyz); xyz.opNotXYZ1(); - xyz.opXYZ1(); } function part3(){ @@ -36,7 +34,6 @@ function part3(){ xyz.tMethod3(new rename.Klass()); xyz.tMethodNotXYZ3(notxyz); xyz.opNotXYZ3(); - xyz.opXYZ3(); } function part4() { @@ -49,7 +46,6 @@ function part4() { xyz.tMethod4(rename.En1); xyz.tMethodNotXYZ4(notxyz); xyz.opNotXYZ4(); - xyz.opXYZ4(); } function part5() { diff --git a/Examples/test-suite/javascript/rename4_runme.js b/Examples/test-suite/javascript/rename4_runme.js index fed50dceb..1c3d8e77f 100644 --- a/Examples/test-suite/javascript/rename4_runme.js +++ b/Examples/test-suite/javascript/rename4_runme.js @@ -10,7 +10,6 @@ function part1() { xyz.tMethod2(0); xyz.tMethodNotXYZ2(notxyz); xyz.opNotXYZ2(); - xyz.opXYZ2(); } function part2() { @@ -23,7 +22,6 @@ function part2() { xyz.tMethod1(0); xyz.tMethodNotXYZ1(notxyz); xyz.opNotXYZ1(); - xyz.opXYZ1(); } function part3(){ @@ -36,7 +34,6 @@ function part3(){ xyz.tMethod3(new rename.Klass()); xyz.tMethodNotXYZ3(notxyz); xyz.opNotXYZ3(); - xyz.opXYZ3(); } function part4() { @@ -49,7 +46,6 @@ function part4() { xyz.tMethod4(rename.En1); xyz.tMethodNotXYZ4(notxyz); xyz.opNotXYZ4(); - xyz.opXYZ4(); } function part5() { diff --git a/Examples/test-suite/javascript/string_simple_runme.js b/Examples/test-suite/javascript/string_simple_runme.js index 39ae84e9e..71fbb7bd0 100644 --- a/Examples/test-suite/javascript/string_simple_runme.js +++ b/Examples/test-suite/javascript/string_simple_runme.js @@ -3,7 +3,7 @@ var string_simple = require("string_simple"); // Test unicode string var str = "olĂ©"; -var copy = string_simple.copy_string(str); +var copy = string_simple.copy_str(str); if (str !== copy) { throw "Error: copy is not equal: original="+str+", copy="+copy; diff --git a/Examples/test-suite/javascript/swig_exception_runme.js b/Examples/test-suite/javascript/swig_exception_runme.js new file mode 100644 index 000000000..55435e947 --- /dev/null +++ b/Examples/test-suite/javascript/swig_exception_runme.js @@ -0,0 +1,30 @@ +var swig_exception = require("swig_exception"); + +var c = new swig_exception.Circle(10); +var s = new swig_exception.Square(10); + +if (swig_exception.Shape.nshapes != 2) { + throw "Shape.nshapes should be 2, actually " + swig_exception.Shape.nshapes; +} + +// ----- Throw exception ----- +try { + c.throwException(); + throw "Exception wasn't thrown"; +} catch (e) { + if (e.message != "OK") { + throw "Exception message should be \"OK\", actually \"" + e.message + "\""; + } +} + +// ----- Delete everything ----- + +c = null; +s = null; +e = null; + +/* FIXME: Garbage collection needs to happen before this check will work. +if (swig_exception.Shape.nshapes != 0) { + throw "Shape.nshapes should be 0, actually " + swig_exception.Shape.nshapes; +} +*/ diff --git a/Examples/test-suite/keyword_rename.i b/Examples/test-suite/keyword_rename.i index 46c3338b3..23c01087d 100644 --- a/Examples/test-suite/keyword_rename.i +++ b/Examples/test-suite/keyword_rename.i @@ -4,6 +4,8 @@ %module keyword_rename +%feature("kwargs"); + #pragma SWIG nowarn=SWIGWARN_PARSE_KEYWORD %inline %{ diff --git a/Examples/test-suite/li_boost_array.i b/Examples/test-suite/li_boost_array.i deleted file mode 100644 index e18140a50..000000000 --- a/Examples/test-suite/li_boost_array.i +++ /dev/null @@ -1,87 +0,0 @@ -%module li_boost_array - -#if defined(SWIGPYTHON) || defined(SWIGRUBY) - -// Hack to use the std::array support for boost::array. -// Is limited as it currently exposes some 'using' bugs in SWIG though. -// For example, the type system fails to see that pointers to std::array -// and pointers to boost::array are the same. - -%{ -#if __cplusplus >= 201103 || (defined(_MSC_VER) && _MSC_VER >= 1900) -// Use C++11 array as this is unfortunately sometimes included by -#include -namespace boost { - using std::array; -} -#else -#include -namespace std { - using boost::array; -} -#endif -%} -namespace boost { - using std::array; -} - -%ignore std::array::fill; // Some older versions of boost don't have this function - -%include - -%template(ArrayInt6) std::array; - -%inline %{ -boost::array arrayOutVal() { - const signed char carray[] = { -2, -1, 0, 0, 1, 2 }; - boost::array myarray; - for (size_t i=0; i<6; ++i) { - myarray[i] = carray[i]; - } - return myarray; -} - -boost::array & arrayOutRef() { - static boost::array a = { -2, -1, 0, 0, 1, 2 }; - return a; -} - -const boost::array & arrayOutConstRef() { - static boost::array a = { -2, -1, 0, 0, 1, 2 }; - return a; -} - -boost::array * arrayOutPtr() { - static boost::array a = { -2, -1, 0, 0, 1, 2 }; - return &a; -} - -boost::array arrayInVal(boost::array myarray) { - for (boost::array::iterator it = myarray.begin(); it!=myarray.end(); ++it) { - *it *= 10; - } - return myarray; -} - -const boost::array & arrayInConstRef(const boost::array & myarray) { - static boost::array a = myarray; - for (boost::array::iterator it = a.begin(); it!=a.end(); ++it) { - *it *= 10; - } - return a; -} - -void arrayInRef(boost::array & myarray) { - for (boost::array::iterator it = myarray.begin(); it!=myarray.end(); ++it) { - *it *= 10; - } -} - -void arrayInPtr(boost::array * myarray) { - for (boost::array::iterator it = myarray->begin(); it!=myarray->end(); ++it) { - *it *= 10; - } -} -%} - -#endif diff --git a/Examples/test-suite/li_boost_shared_ptr_bits.i b/Examples/test-suite/li_boost_shared_ptr_bits.i index b61fd2aa6..7cf84010e 100644 --- a/Examples/test-suite/li_boost_shared_ptr_bits.i +++ b/Examples/test-suite/li_boost_shared_ptr_bits.i @@ -4,6 +4,10 @@ #define SHARED_PTR_WRAPPERS_IMPLEMENTED #endif +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + #if defined(SHARED_PTR_WRAPPERS_IMPLEMENTED) %include diff --git a/Examples/test-suite/li_boost_shared_ptr_director.i b/Examples/test-suite/li_boost_shared_ptr_director.i new file mode 100644 index 000000000..b2d9fc131 --- /dev/null +++ b/Examples/test-suite/li_boost_shared_ptr_director.i @@ -0,0 +1,138 @@ +%module(directors="1") "li_boost_shared_ptr_director" + +%{ +#include +%} + +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGD) || defined(SWIGOCTAVE) || defined(SWIGRUBY) || defined(SWIGR) +#define SHARED_PTR_WRAPPERS_IMPLEMENTED +#endif + +#if defined(SHARED_PTR_WRAPPERS_IMPLEMENTED) + +%include +%shared_ptr(C); +%feature("director") Base; + +%inline %{ +struct C { + C() : m(1) {} + C(int n) : m(n) {} + int get_m() { return m; } +private: + int m; +}; + +struct Base { + Base() {} + virtual boost::shared_ptr ret_c_shared_ptr() = 0; + virtual C ret_c_by_value() = 0; + virtual int take_c_by_value(C c) = 0; + virtual int take_c_by_ref(C& c) = 0; + virtual int take_c_by_pointer(C* c) = 0; + virtual int take_c_by_pointer_ref(C*const& c) = 0; + virtual int take_c_shared_ptr_by_value(boost::shared_ptr c) = 0; + virtual int take_c_shared_ptr_by_ref(boost::shared_ptr& c) = 0; + virtual int take_c_shared_ptr_by_pointer(boost::shared_ptr* c) = 0; + virtual int take_c_shared_ptr_by_pointer_ref(boost::shared_ptr*const&c) = 0; + virtual int take_many_args( + C v1, C v2, + C &r1, C &r2, + C *p1, C *p2, + C *const& cr1, C *const& cr2, + boost::shared_ptr sv1, boost::shared_ptr sv2, + boost::shared_ptr &sr1, boost::shared_ptr &sr2, + boost::shared_ptr *sp1, boost::shared_ptr *sp2, + boost::shared_ptr *const& spr1, boost::shared_ptr *const& spr2 + ) = 0; + virtual ~Base() {} +}; + +int call_ret_c_shared_ptr(Base* b) { + boost::shared_ptr ptr = b->ret_c_shared_ptr(); + if (ptr) { + return ptr->get_m(); + } else { + return -1; + } +} + +int call_ret_c_by_value(Base* b) { + C c = b->ret_c_by_value(); + return c.get_m(); +} + +int call_take_c_by_value(Base* b) { + C c(5); + return b->take_c_by_value(c); +} + +int call_take_c_by_ref(Base* b) { + C c(6); + return b->take_c_by_ref(c); +} + +int call_take_c_by_pointer(Base* b) { + C c(7); + return b->take_c_by_pointer(&c); +} + +int call_take_c_by_pointer_ref(Base* b) { + C c(8); + C* p(&c); + return b->take_c_by_pointer_ref(p); +} + +int call_take_c_by_pointer_with_null(Base* b) { + C* p = NULL; + return b->take_c_by_pointer(p); +} + +int call_take_c_by_pointer_ref_with_null(Base* b) { + C* p = NULL; + return b->take_c_by_pointer_ref(p); +} + +int call_take_c_shared_ptr_by_value(Base* b) { + boost::shared_ptr ptr(new C(9)); + return b->take_c_shared_ptr_by_value(ptr); +} + +int call_take_c_shared_ptr_by_value_with_null(Base* b) { + boost::shared_ptr ptr; + return b->take_c_shared_ptr_by_value(ptr); +} + +int call_take_c_shared_ptr_by_ref(Base* b) { + boost::shared_ptr ptr(new C(10)); + return b->take_c_shared_ptr_by_ref(ptr); +} + +int call_take_c_shared_ptr_by_ref_with_null(Base* b) { + boost::shared_ptr ptr; + return b->take_c_shared_ptr_by_ref(ptr); +} + +int call_take_c_shared_ptr_by_pointer(Base* b) { + boost::shared_ptr ptr(new C(11)); + return b->take_c_shared_ptr_by_pointer(&ptr); +} + +int call_take_c_shared_ptr_by_pointer_with_null(Base* b) { + boost::shared_ptr ptr; + return b->take_c_shared_ptr_by_pointer(&ptr); +} + +int call_take_c_shared_ptr_by_pointer_ref(Base* b) { + boost::shared_ptr *ptr = new boost::shared_ptr(new C(12)); + return b->take_c_shared_ptr_by_pointer_ref(ptr); +} + +int call_take_c_shared_ptr_by_pointer_ref_with_null(Base* b) { + boost::shared_ptr *ptr = new boost::shared_ptr(); + return b->take_c_shared_ptr_by_pointer_ref(ptr); +} + +%} + +#endif diff --git a/Examples/test-suite/li_carrays.i b/Examples/test-suite/li_carrays.i index 45c6537d5..a39f3a2c9 100644 --- a/Examples/test-suite/li_carrays.i +++ b/Examples/test-suite/li_carrays.i @@ -6,6 +6,7 @@ %array_functions(int,intArray); %array_class(double, doubleArray); +%array_class(short, shortArray); %inline %{ typedef struct { @@ -26,3 +27,13 @@ AB globalABArray[3]; %array_class(XY, XYArray) %array_functions(AB, ABArray) +%inline %{ +short sum_array(short x[5]) { + short sum = 0; + int i; + for (i=0; i<5; i++) { + sum = sum + x[i]; + } + return sum; +} +%} diff --git a/Examples/test-suite/li_carrays_cpp.i b/Examples/test-suite/li_carrays_cpp.i index c4743420e..2a80e7823 100644 --- a/Examples/test-suite/li_carrays_cpp.i +++ b/Examples/test-suite/li_carrays_cpp.i @@ -6,6 +6,7 @@ %array_functions(int,intArray); %array_class(double, doubleArray); +%array_class(short, shortArray); %inline %{ typedef struct { @@ -26,3 +27,13 @@ AB globalABArray[3]; %array_class(XY, XYArray) %array_functions(AB, ABArray) +%inline %{ +short sum_array(short x[5]) { + short sum = 0; + int i; + for (i=0; i<5; i++) { + sum = sum + x[i]; + } + return sum; +} +%} diff --git a/Examples/test-suite/li_implicit.i b/Examples/test-suite/li_implicit.i index 0ce10dd6e..9f3ea318b 100644 --- a/Examples/test-suite/li_implicit.i +++ b/Examples/test-suite/li_implicit.i @@ -1,4 +1,7 @@ -%module("nocastmode") li_implicit +%module li_implicit + +// Tests nocastmode + #pragma SWIG nowarn=SWIGWARN_PP_CPP_WARNING %include implicit.i diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index 5fdc5fa35..5bde387a3 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -4,6 +4,12 @@ #if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) #pragma GCC diagnostic ignored "-Wdeprecated-declarations" // auto_ptr deprecation #endif + +#if defined(__clang__) +#pragma clang diagnostic push +// Suppress 'auto_ptr<>' is deprecated +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif %} #if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) @@ -12,11 +18,29 @@ %auto_ptr(Klass) -%inline %{ - +%{ +#if __cplusplus < 201703L #include +#else +// Simple std::auto_ptr implementation for testing after its removal in C++17 +namespace std { + template class auto_ptr { + T *ptr; + public: + auto_ptr(T *ptr = 0) : ptr(ptr) {} + auto_ptr(auto_ptr&& a) : ptr(a.ptr) { a.ptr = 0;} + ~auto_ptr() { delete ptr; } + T *release() { T *p = ptr; ptr = 0; return p; } + auto_ptr& operator=(auto_ptr&& a) { if (&a != this) { delete ptr; ptr = a.ptr; a.ptr = 0; } return *this; } + }; +} +#endif + #include #include "swig_examples_lock.h" +%} + +%inline %{ class Klass { public: diff --git a/Examples/test-suite/li_std_deque.i b/Examples/test-suite/li_std_deque.i index 152bc86c1..c2f4a7f45 100644 --- a/Examples/test-suite/li_std_deque.i +++ b/Examples/test-suite/li_std_deque.i @@ -36,8 +36,8 @@ std::deque half(const std::deque& v) { } void halve_in_place(std::deque& v) { - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::deque::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } %} diff --git a/Examples/test-suite/li_std_except.i b/Examples/test-suite/li_std_except.i index fc886dca7..60bce999d 100644 --- a/Examples/test-suite/li_std_except.i +++ b/Examples/test-suite/li_std_except.i @@ -2,13 +2,12 @@ %include +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) %{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +#define TESTCASE_THROW1(T1) %} - %inline %{ struct E1 : public std::exception { @@ -19,21 +18,23 @@ }; struct Test { - int foo1() throw(std::bad_exception) { return 0; } - int foo2() throw(std::logic_error) { return 0; } - int foo3() throw(E1) { return 0; } - int foo4() throw(E2) { return 0; } + int foo1() TESTCASE_THROW1(std::bad_exception) { return 0; } + int foo2() TESTCASE_THROW1(std::logic_error) { return 0; } + int foo3() TESTCASE_THROW1(E1) { return 0; } + int foo4() TESTCASE_THROW1(E2) { return 0; } // all the STL exceptions... - void throw_bad_exception() throw(std::bad_exception) { throw std::bad_exception(); } - void throw_domain_error() throw(std::domain_error) { throw std::domain_error("oops"); } - void throw_exception() throw(std::exception) { throw std::exception(); } - void throw_invalid_argument() throw(std::invalid_argument) { throw std::invalid_argument("oops"); } - void throw_length_error() throw(std::length_error) { throw std::length_error("oops"); } - void throw_logic_error() throw(std::logic_error) { throw std::logic_error("oops"); } - void throw_out_of_range() throw(std::out_of_range) { throw std::out_of_range("oops"); } - void throw_overflow_error() throw(std::overflow_error) { throw std::overflow_error("oops"); } - void throw_range_error() throw(std::range_error) { throw std::range_error("oops"); } - void throw_runtime_error() throw(std::runtime_error) { throw std::runtime_error("oops"); } - void throw_underflow_error() throw(std::underflow_error) { throw std::underflow_error("oops"); } + void throw_bad_cast() TESTCASE_THROW1(std::bad_cast) { throw std::bad_cast(); } + void throw_bad_exception() TESTCASE_THROW1(std::bad_exception) { throw std::bad_exception(); } + void throw_domain_error() TESTCASE_THROW1(std::domain_error) { throw std::domain_error("oops"); } + void throw_exception() TESTCASE_THROW1(std::exception) { throw std::exception(); } + void throw_invalid_argument() TESTCASE_THROW1(std::invalid_argument) { throw std::invalid_argument("oops"); } + void throw_length_error() TESTCASE_THROW1(std::length_error) { throw std::length_error("oops"); } + void throw_logic_error() TESTCASE_THROW1(std::logic_error) { throw std::logic_error("oops"); } + void throw_out_of_range() TESTCASE_THROW1(std::out_of_range) { throw std::out_of_range("oops"); } + void throw_overflow_error() TESTCASE_THROW1(std::overflow_error) { throw std::overflow_error("oops"); } + void throw_range_error() TESTCASE_THROW1(std::range_error) { throw std::range_error("oops"); } + void throw_runtime_error() TESTCASE_THROW1(std::runtime_error) { throw std::runtime_error("oops"); } + void throw_underflow_error() TESTCASE_THROW1(std::underflow_error) { throw std::underflow_error("oops"); } }; %} + diff --git a/Examples/test-suite/li_std_except_as_class.i b/Examples/test-suite/li_std_except_as_class.i index 01ed1f07c..3d9706c80 100644 --- a/Examples/test-suite/li_std_except_as_class.i +++ b/Examples/test-suite/li_std_except_as_class.i @@ -5,23 +5,23 @@ * if there were also functions throwing 'std::logic_error' and * 'std::exception' then the bug would not be fully replicated */ +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW2(T1, T2) throw(T1, T2) %{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +#define TESTCASE_THROW2(T1, T2) %} %{ #include #include -void test_domain_error() throw(std::domain_error) +void test_domain_error() TESTCASE_THROW2(std::domain_error, int) { throw std::domain_error("std::domain_error"); } %} %include #define SWIG_STD_EXCEPTIONS_AS_CLASSES %include -void test_domain_error() throw(std::domain_error) +void test_domain_error() TESTCASE_THROW2(std::domain_error, int) { throw std::domain_error("std::domain_error"); } %inline %{ @@ -31,3 +31,4 @@ bool is_python_builtin() { return true; } bool is_python_builtin() { return false; } #endif %} + diff --git a/Examples/test-suite/li_std_list.i b/Examples/test-suite/li_std_list.i index bae475eea..2ed5b9ad7 100644 --- a/Examples/test-suite/li_std_list.i +++ b/Examples/test-suite/li_std_list.i @@ -1,6 +1,7 @@ %module li_std_list %include "std_list.i" +%include "std_string.i" %{ #include @@ -8,19 +9,18 @@ #include %} -namespace std { - %template(IntList) list; -} - +%template(BoolList) std::list; +%template(CharList) std::list; +%template(ShortList) std::list; +%template(IntList) std::list; +%template(LongList) std::list; +%template(UCharList) std::list; +%template(UIntList) std::list; +%template(UShortList) std::list; +%template(ULongList) std::list; +%template(FloatList) std::list; %template(DoubleList) std::list; - -%inline %{ -typedef float Real; -%} - -namespace std { - %template(RealList) list; -} +%template(StringList) std::list; %inline %{ @@ -30,17 +30,43 @@ double average(std::list v) { void halve_in_place(std::list& v) { - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::list::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } struct Struct { double num; Struct() : num(0.0) {} Struct(double d) : num(d) {} -// bool operator==(const Struct &other) { return (num == other.num); } +}; + +const std::list & CopyContainerStruct(const std::list & container) { return container; } +const std::list & CopyContainerStructPtr(const std::list & container) { return container; } +const std::list & CopyContainerStructConstPtr(const std::list & container) { return container; } + +const std::list & listreal(const std::list & list) { return list; } + +const std::list & listint(const std::list & list) { return list; } +const std::list & listintptr(const std::list & list) { return list; } +const std::list & listintconstptr(const std::list & list) { return list; } + +const std::list & liststruct(const std::list & list) { return list; } +const std::list & liststructptr(const std::list & list) { return list; } +const std::list & liststructconstptr(const std::list & list) { return list; } + +enum Fruit { + APPLE, + BANANNA, + PEAR, + KIWI, }; %} - - +#if !defined(SWIGR) +%template(IntPtrList) std::list; +%template(IntConstPtrList) std::list; +#endif +%template(StructList) std::list; +%template(StructPtrList) std::list; +%template(StructConstPtrList) std::list; +%template(FruitList) std::list; diff --git a/Examples/test-suite/li_std_map.i b/Examples/test-suite/li_std_map.i index bf24c35e1..161ec6aca 100644 --- a/Examples/test-suite/li_std_map.i +++ b/Examples/test-suite/li_std_map.i @@ -1,6 +1,10 @@ %module("templatereduce") li_std_map %feature("trackobjects"); +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %inline %{ namespace another { struct map { @@ -117,4 +121,25 @@ namespace std { } } +%ignore LengthCompare::operator(); +%inline %{ +struct LengthCompare { + bool operator() (std::string s1, std::string s2) const { + return s1.size() < s2.size(); + } +}; +%} +// A map sorted by string lengths +%template(StringLengthNumberMap) std::map< std::string, int, LengthCompare >; + +%inline %{ +std::map< std::string, int, LengthCompare > MyMap; +void populate(std::map< std::string, int, LengthCompare >&m) { + m["aa"] = 2; + m["xxxx"] = 4; + m["a"] = 1; + m["aaaaa"] = 5; + m["zzz"] = 3; +} +%} diff --git a/Examples/test-suite/li_std_set.i b/Examples/test-suite/li_std_set.i index 2dcc2f17c..507272d8d 100644 --- a/Examples/test-suite/li_std_set.i +++ b/Examples/test-suite/li_std_set.i @@ -1,5 +1,5 @@ /* - * a test of set containers. + * a test of set containers. * Languages should define swig::LANGUAGE_OBJ to be * an entity of their native pointer type which can be * included in a STL container. @@ -13,22 +13,42 @@ %include %include -%include %include -%template(set_string) std::set; -%template(set_int) std::multiset; - - -%template(v_int) std::vector; +// Use language macros since Java and C# don't have multiset support (yet) +// and uses different naming conventions. +#if defined(SWIGRUBY) || defined(SWIGPYTHON) + %include + %template(set_int) std::multiset; + %template(v_int) std::vector; + %template(set_string) std::set; +#elif defined(SWIGJAVA) || defined(SWIGCSHARP) + // This operator is only defined because it's needed to store objects of + // type Foo in std::set in C++, we don't need to wrap it. + %ignore operator<; + %inline %{ + struct Foo + { + explicit Foo(int n) : n(n) {} + int n; + friend bool operator<(Foo foo1, Foo foo2) + { + return foo1.n < foo2.n; + } + }; + %} + %template(IntSet) std::set; + %template(StringSet) std::set; + %template(FooSet) std::set; +#endif #if defined(SWIGRUBY) -%template(LanguageSet) std::set; +%template(LanguageSet) std::set; #endif #if defined(SWIGPYTHON) -%template(pyset) std::set; +%template(pyset) std::set; #endif diff --git a/Examples/test-suite/li_std_string.i b/Examples/test-suite/li_std_string.i index a1a55ed85..47a9090b7 100644 --- a/Examples/test-suite/li_std_string.i +++ b/Examples/test-suite/li_std_string.i @@ -6,6 +6,11 @@ %apply std::string& INOUT { std::string &inout } #endif +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) +%{ +#define TESTCASE_THROW1(T1) +%} %inline %{ @@ -17,6 +22,12 @@ const std::string& test_const_reference(const std::string &x) { return x; } +void test_const_reference_returning_void(const std::string &) { +} + +void test_const_reference_returning_void(const std::string &, int) { +} + void test_pointer(std::string *x) { } @@ -49,32 +60,23 @@ void test_reference_inout(std::string &inout) { inout += inout; } -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - -void test_throw() throw(std::string){ +void test_throw() TESTCASE_THROW1(std::string){ static std::string x = "test_throw message"; throw x; } -void test_const_reference_throw() throw(const std::string &){ +void test_const_reference_throw() TESTCASE_THROW1(const std::string &){ static std::string x = "test_const_reference_throw message"; throw x; } -void test_pointer_throw() throw(std::string *) { +void test_pointer_throw() TESTCASE_THROW1(std::string *) { throw new std::string("foo"); } -void test_const_pointer_throw() throw(const std::string *) { +void test_const_pointer_throw() TESTCASE_THROW1(const std::string *) { throw new std::string("foo"); } - -#if defined(_MSC_VER) - #pragma warning(default: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - %} /* Old way, now std::string is a %naturalvar by default @@ -154,6 +156,5 @@ public: const char *get_null(const char *a) { return a == 0 ? a : "non-null"; } - - %} + diff --git a/Examples/test-suite/li_std_string_extra.i b/Examples/test-suite/li_std_string_extra.i index 6bef12ff4..1fc2225ca 100644 --- a/Examples/test-suite/li_std_string_extra.i +++ b/Examples/test-suite/li_std_string_extra.i @@ -49,6 +49,14 @@ std::basic_string,std::allocator > test_value_ return x; } +std::basic_string,std::allocator > test_value_basic_overload(std::basic_string,std::allocator > x) { + return x; +} + +std::basic_string,std::allocator > test_value_basic_overload(int) { + return "int"; +} + #ifdef SWIGPYTHON_BUILTIN bool is_python_builtin() { return true; } #else diff --git a/Examples/test-suite/li_std_vector.i b/Examples/test-suite/li_std_vector.i index ada146cc4..33fb79720 100644 --- a/Examples/test-suite/li_std_vector.i +++ b/Examples/test-suite/li_std_vector.i @@ -48,8 +48,8 @@ std::vector half(const std::vector& v) { } void halve_in_place(std::vector& v) { - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::vector::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } struct Struct { diff --git a/Examples/test-suite/li_std_vector_back_reference.i b/Examples/test-suite/li_std_vector_back_reference.i new file mode 100644 index 000000000..be41f4740 --- /dev/null +++ b/Examples/test-suite/li_std_vector_back_reference.i @@ -0,0 +1,14 @@ +%module li_std_vector_back_reference + +%include + +%inline %{ +// #include +struct Wheel { + int size; + Wheel(int sz = 0) : size(sz) {} +// ~Wheel() { std::cout << "~Wheel" << std::endl; } +}; +%} + +%template(VectorWheel) std::vector; diff --git a/Examples/test-suite/li_std_vector_extra.i b/Examples/test-suite/li_std_vector_extra.i index 531898a0e..70b776b37 100644 --- a/Examples/test-suite/li_std_vector_extra.i +++ b/Examples/test-suite/li_std_vector_extra.i @@ -12,17 +12,6 @@ #include #include #include - - -#if defined(__clang__) -// Suppress: -// warning: destination for this 'memset' call is a pointer to dynamic class -// 'Test::B'; vtable pointer will be overwritten [-Wdynamic-class-memaccess] -// memset(v_def,0,sizeof(Type)); -// Better generated code is probably needed though -#pragma clang diagnostic ignored "-Wdynamic-class-memaccess" -#endif - %} namespace std { @@ -73,8 +62,8 @@ std::vector half(const std::vector& v) { } void halve_in_place(std::vector& v) { - std::transform(v.begin(),v.end(),v.begin(), - std::bind2nd(std::divides(),2.0)); + for (std::vector::iterator it = v.begin(); it != v.end(); ++it) + *it /= 2.0; } %} @@ -140,6 +129,7 @@ std::vector vecStr(std::vector v) { double *makeDoublePtr(double v) { return new double(v); } int extractInt(int *p) { return *p; } short extractConstShort(const short *p) { return *p; } + short extractConstShort2(std::vector::value_type p) { return *p; } %} %template(pyvector) std::vector; diff --git a/Examples/test-suite/li_std_vector_ptr.i b/Examples/test-suite/li_std_vector_ptr.i index 4d6794717..dcf1128e0 100644 --- a/Examples/test-suite/li_std_vector_ptr.i +++ b/Examples/test-suite/li_std_vector_ptr.i @@ -5,12 +5,29 @@ %template(IntPtrVector) std::vector; +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %inline %{ #include using namespace std; int* makeIntPtr(int v) { return new int(v); } +std::vector::value_type makeIntPtr2(int v) { + return new int(v); +} +int getIntValue(int *p) { + return *p; +} +int getIntValue2(std::vector::const_reference p) { + return *p; +} +int getIntValue3(std::vector::reference p) { + return *p; +} + double* makeDoublePtr(double v) { return new double(v); } diff --git a/Examples/test-suite/li_std_wstring.i b/Examples/test-suite/li_std_wstring.i index 80f860338..55d45383e 100644 --- a/Examples/test-suite/li_std_wstring.i +++ b/Examples/test-suite/li_std_wstring.i @@ -1,29 +1,18 @@ %module li_std_wstring -%include + +// The languages below are yet to provide std_wstring.i +#if !(defined(SWIGD) || defined(SWIGGO) || defined(SWIGGUILE) || defined(SWIGJAVASCRIPT) || defined(SWIGLUA) || defined(SWIGMZSCHEME) || defined(SWIGOCAML) || defined(SWIGOCTAVE) || defined(SWIGPERL) || defined(SWIGPHP) || defined(SWIGR) || defined(SWIGSCILAB)) + %include +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) +%{ +#define TESTCASE_THROW1(T1) +%} %inline %{ - -struct A : std::wstring -{ - A(const std::wstring& s) : std::wstring(s) - { - } -}; - -struct B -{ - B(const std::wstring& s) : cname(0), name(s), a(s) - { - } - - char *cname; - std::wstring name; - A a; - -}; - +#include wchar_t test_wcvalue(wchar_t x) { return x; @@ -57,47 +46,31 @@ const std::wstring& test_const_reference(const std::wstring &x) { void test_pointer(std::wstring *x) { } -std::wstring *test_pointer_out() { - static std::wstring x = L"x"; - return &x; -} - void test_const_pointer(const std::wstring *x) { } -const std::wstring *test_const_pointer_out() { - static std::wstring x = L"x"; - return &x; -} - void test_reference(std::wstring &x) { } -std::wstring& test_reference_out() { - static std::wstring x = L"x"; - return x; +bool test_equal_abc(const std::wstring &s) { + return L"abc" == s; } -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - -void test_throw() throw(std::wstring){ - static std::wstring x = L"x"; +void test_throw() TESTCASE_THROW1(std::wstring){ + static std::wstring x = L"throwing test_throw"; throw x; } -#if defined(_MSC_VER) - #pragma warning(default: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +const char * non_utf8_c_str() { + return "h\xe9llo"; +} -#ifdef SWIGPYTHON_BUILTIN -bool is_python_builtin() { return true; } -#else -bool is_python_builtin() { return false; } -#endif +size_t size_wstring(const std::wstring& s) { + return s.size(); +} %} +#endif diff --git a/Examples/test-suite/li_std_wstring_inherit.i b/Examples/test-suite/li_std_wstring_inherit.i new file mode 100644 index 000000000..54c6bd8c4 --- /dev/null +++ b/Examples/test-suite/li_std_wstring_inherit.i @@ -0,0 +1,39 @@ +%module li_std_wstring_inherit +%include +%include + + +%inline %{ + +struct A : std::wstring +{ + A(const std::wstring& s) : std::wstring(s) + { + } +}; + +struct B +{ + B(const std::wstring& s) : cname(0), name(s), a(s) + { + } + + char *cname; + std::wstring name; + A a; + +}; + +std::wstring test_value(std::wstring x) { + return x; +} + +#ifdef SWIGPYTHON_BUILTIN +bool is_python_builtin() { return true; } +#else +bool is_python_builtin() { return false; } +#endif + +%} + + diff --git a/Examples/test-suite/lua/Makefile.in b/Examples/test-suite/lua/Makefile.in index 7a77bbb9e..63b8692b1 100644 --- a/Examples/test-suite/lua/Makefile.in +++ b/Examples/test-suite/lua/Makefile.in @@ -58,9 +58,3 @@ run_testcase = \ clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' lua_clean - -cvsignore: - @echo '*wrap* *.so *.dll *.exp *.lib' - @echo Makefile - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.lua; done - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do if grep -q $${i}_runme.lua CVS/Entries ; then echo $${i}_runme.lua; fi; done diff --git a/Examples/test-suite/lua/abstract_access_runme.lua b/Examples/test-suite/lua/abstract_access_runme.lua index c1d836136..70467ee2b 100644 --- a/Examples/test-suite/lua/abstract_access_runme.lua +++ b/Examples/test-suite/lua/abstract_access_runme.lua @@ -6,7 +6,7 @@ local env = _ENV -- Lua 5.2 if not env then env = getfenv () end -- Lua 5.1 setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end}) --- trying to instantiate pure virual classes +-- trying to instantiate pure virtual classes -- should fail assert(pcall(abstract_access.A)==false) assert(pcall(abstract_access.B)==false) diff --git a/Examples/test-suite/lua/li_std_string_runme.lua b/Examples/test-suite/lua/li_std_string_runme.lua index 956bea0fc..a36bf7ef6 100644 --- a/Examples/test-suite/lua/li_std_string_runme.lua +++ b/Examples/test-suite/lua/li_std_string_runme.lua @@ -32,8 +32,8 @@ assert(is_std_string(cobj) and cobj:c_str()=="x") -- check type & value test_const_pointer(cobj) --- this shouldnt work, but it does --- swig doesnt appear to diff between const object ptrs & object ptrs very well +-- this shouldn't work, but it does +-- swig doesn't appear to diff between const object ptrs & object ptrs very well test_pointer(cobj) -- this wants an non const object (give it a const one!) -- refs are also wrappered as ptrs (unless the correct typemaps are applied) diff --git a/Examples/test-suite/lua/newobject2_runme.lua b/Examples/test-suite/lua/newobject2_runme.lua index cf6c87ae7..748c95372 100644 --- a/Examples/test-suite/lua/newobject2_runme.lua +++ b/Examples/test-suite/lua/newobject2_runme.lua @@ -1,8 +1,8 @@ require("import") -- the import fn import("newobject2",true) -- import code -foo1 = newobject2.makeFoo() -- lua doesnt yet support static fns properly -assert(newobject2.fooCount() == 1) -- lua doesnt yet support static fns properly +foo1 = newobject2.makeFoo() -- lua doesn't yet support static fns properly +assert(newobject2.fooCount() == 1) -- lua doesn't yet support static fns properly foo2 = newobject2.makeFoo() assert(newobject2.fooCount() == 2) diff --git a/Examples/test-suite/lua/overload_complicated_runme.lua b/Examples/test-suite/lua/overload_complicated_runme.lua index e8ef43107..3decfa87d 100644 --- a/Examples/test-suite/lua/overload_complicated_runme.lua +++ b/Examples/test-suite/lua/overload_complicated_runme.lua @@ -12,11 +12,11 @@ assert(oc.foo(1,1,"test",1) == 15) p1 = oc.Pop(nil) p1 = oc.Pop(nil,false) -assert(p1:hip(true) == 701) +assert(p1:hip(false) == 701) assert(p1:hip(nil) == 702) -assert(p1:hop(true) == 801) +assert(p1:hop(false) == 801) assert(p1:hop(nil) == 805) -assert(oc.muzak(true) == 3001) +assert(oc.muzak(false) == 3001) assert(oc.muzak(nil) == 3002) diff --git a/Examples/test-suite/lua/overload_null_runme.lua b/Examples/test-suite/lua/overload_null_runme.lua new file mode 100644 index 000000000..69b7de2db --- /dev/null +++ b/Examples/test-suite/lua/overload_null_runme.lua @@ -0,0 +1,41 @@ +require("import") -- the import fn +import("overload_null") -- import lib into global + +o = overload_null.Overload() +x = overload_null.X() + +assert(1 == o:byval1(x)) +assert(2 == o:byval1(nil)) + +assert(3 == o:byval2(nil)) +assert(4 == o:byval2(x)) + +assert(5 == o:byref1(x)) +assert(6 == o:byref1(nil)) + +assert(7 == o:byref2(nil)) +assert(8 == o:byref2(x)) + +assert(9 == o:byconstref1(x)) +assert(10 == o:byconstref1(nil)) + +assert(11 == o:byconstref2(nil)) +assert(12 == o:byconstref2(x)) + +-- const pointer references +assert(13 == o:byval1cpr(x)) +assert(14 == o:byval1cpr(nil)) + +assert(15 == o:byval2cpr(nil)) +assert(16 == o:byval2cpr(x)) + +-- forward class declaration +assert(17 == o:byval1forwardptr(x)) +assert(18 == o:byval1forwardptr(nil)) + +assert(19 == o:byval2forwardptr(nil)) +assert(20 == o:byval2forwardptr(x)) + +assert(21 == o:byval1forwardref(x)) + +assert(22 == o:byval2forwardref(x)) diff --git a/Examples/test-suite/member_funcptr_galore.i b/Examples/test-suite/member_funcptr_galore.i index 9a012f306..27c2f02a7 100644 --- a/Examples/test-suite/member_funcptr_galore.i +++ b/Examples/test-suite/member_funcptr_galore.i @@ -1,5 +1,17 @@ %module member_funcptr_galore +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) extra2; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) extra3; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) pp2; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) pp3; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) pp5; + +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ccextra2; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ccextra3; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc2; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc3; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc5; + %{ #if defined(__SUNPRO_CC) #pragma error_messages (off, badargtype2w) /* Formal argument ... is being passed extern "C" ... */ @@ -27,6 +39,8 @@ public: void move(double dx, double dy); virtual double area(Shape &ref, int & (FunkSpace::Funktions::*d)(const int &, int)) { return 0.0; } + virtual double area_const(Shape &ref, int & (FunkSpace::Funktions::*)(const int &, int) const) { return 0.0; } // Note: unnamed parameter + virtual double zyx(int (FunkSpace::Funktions::*)() const) { return 0.0; } // Note: unnamed parameter virtual double abc(Thing ts, Thing< const Space::Shape * > tda[]) { return 0.0; } virtual ~Shape() {} }; @@ -55,6 +69,10 @@ double do_op(Space::Shape *s, double (Space::Shape::*m)(void)) { return (s->*m)(); } +double do_op_const(Space::Shape *s, double (Space::Shape::*m)(void) const) { + return (s->*m)(); +} + double (Space::Shape::*areapt(Space::Shape &ref, int & (FunkSpace::Funktions::*d)(const int &, int)))(Space::Shape &, int & (FunkSpace::Funktions::*d)(const int &, int)) { return &Space::Shape::area; } @@ -75,6 +93,7 @@ double (Space::Shape::*abcvar)(Thing, Thing< const Space::Shape * >[]) = /* Some constants */ %constant double (Space::Shape::*AREAPT)(Space::Shape &, int & (FunkSpace::Funktions::*)(const int &, int)) = &Space::Shape::area; +%constant double (Space::Shape::*AREAPT_CONST)(Space::Shape &, int & (FunkSpace::Funktions::*)(const int &, int) const) = &Space::Shape::area_const; %constant double (Space::Shape::*PERIMPT)(Thing, Thing< const Space::Shape * >[]) = &Space::Shape::abc; %constant double (Space::Shape::*NULLPT)(void) = 0; @@ -94,3 +113,115 @@ int call3(int & (FunkSpace::Funktions::*d)(const int &, int), int a, int b) { Fu int unreal1(double (Space::Shape::*memptr)(Space::Shape &, int & (FunkSpace::Funktions::*)(const int &, int))) { return 0; } int unreal2(double (Space::Shape::*memptr)(Thing)) { return 0; } %} + + +%inline %{ +struct Funcs { + short FF(bool) { return 0; } + short CC(bool) const { return 0; } +}; + +class MemberFuncPtrs +{ +public: + // member const function pointers, unnamed parameters + int aaa1(short (Funcs::* )(bool) const) const; + int aaa2(short (Funcs::* const *&)(bool) const) const; + int aaa3(short (Funcs::* *& )(bool) const) const; + int aaa4(short (Funcs::* *const& )(bool) const) const; + int aaa5(short (Funcs::* & )(bool) const) const; + int aaa6(short (Funcs::* const)(bool) const) const; + int aaa7(short (Funcs::* const&)(bool) const) const; + + // member non-const function pointers, unnamed parameters + int bbb1(short (Funcs::* )(bool)) const; + int bbb2(short (Funcs::* const *&)(bool)) const; + int bbb3(short (Funcs::* *& )(bool)) const; + int bbb4(short (Funcs::* *const& )(bool)) const; + int bbb5(short (Funcs::* & )(bool)) const; + int bbb6(short (Funcs::* const)(bool)) const; + int bbb7(short (Funcs::* const&)(bool)) const; + + // member const function pointers, named parameters + int ppp1(short (Funcs::* pp1)(bool) const) const; + int ppp2(short (Funcs::* const *& pp2)(bool) const) const; + int ppp3(short (Funcs::* *& pp3)(bool) const) const; + int ppp4(short (Funcs::* *const& pp4)(bool) const) const; + int ppp5(short (Funcs::* & pp5)(bool) const) const; + int ppp6(short (Funcs::* const pp6)(bool) const) const; + int ppp7(short (Funcs::* const& pp7)(bool) const) const; + + // member non-const function pointers, named parameters + int qqq1(short (Funcs::* qq1)(bool)) const; + int qqq2(short (Funcs::* const *& qq2)(bool)) const; + int qqq3(short (Funcs::* *& qq3)(bool)) const; + int qqq4(short (Funcs::* *const& qq4)(bool)) const; + int qqq5(short (Funcs::* & qq5)(bool)) const; + int qqq6(short (Funcs::* const qq6)(bool)) const; + int qqq7(short (Funcs::* const& qq7)(bool)) const; +}; + +// member const function pointers, unnamed parameters +int MemberFuncPtrs::aaa1(short (Funcs::* )(bool) const) const { return 0; } +int MemberFuncPtrs::aaa2(short (Funcs::* const *&)(bool) const) const { return 0; } +int MemberFuncPtrs::aaa3(short (Funcs::* *& )(bool) const) const { return 0; } +int MemberFuncPtrs::aaa4(short (Funcs::* *const& )(bool) const) const { return 0; } +int MemberFuncPtrs::aaa5(short (Funcs::* & )(bool) const) const { return 0; } +int MemberFuncPtrs::aaa6(short (Funcs::* const)(bool) const) const { return 0; } +int MemberFuncPtrs::aaa7(short (Funcs::* const&)(bool) const) const { return 0; } + +// member non-const function pointers, unnamed parameters +int MemberFuncPtrs::bbb1(short (Funcs::* )(bool)) const { return 0; } +int MemberFuncPtrs::bbb2(short (Funcs::* const *&)(bool)) const { return 0; } +int MemberFuncPtrs::bbb3(short (Funcs::* *& )(bool)) const { return 0; } +int MemberFuncPtrs::bbb4(short (Funcs::* *const& )(bool)) const { return 0; } +int MemberFuncPtrs::bbb5(short (Funcs::* & )(bool)) const { return 0; } +int MemberFuncPtrs::bbb6(short (Funcs::* const)(bool)) const { return 0; } +int MemberFuncPtrs::bbb7(short (Funcs::* const&)(bool)) const { return 0; } + +// member const function pointers, named parameters +int MemberFuncPtrs::ppp1(short (Funcs::* pp1)(bool) const) const { return 0; } +int MemberFuncPtrs::ppp2(short (Funcs::* const *& pp2)(bool) const) const { return 0; } +int MemberFuncPtrs::ppp3(short (Funcs::* *& pp3)(bool) const) const { return 0; } +int MemberFuncPtrs::ppp4(short (Funcs::* *const& pp4)(bool) const) const { return 0; } +int MemberFuncPtrs::ppp5(short (Funcs::* & pp5)(bool) const) const { return 0; } +int MemberFuncPtrs::ppp6(short (Funcs::* const pp6)(bool) const) const { return 0; } +int MemberFuncPtrs::ppp7(short (Funcs::* const& pp7)(bool) const) const { return 0; } + +// member non-const function pointers, named parameters +int MemberFuncPtrs::qqq1(short (Funcs::* qq1)(bool)) const { return 0; } +int MemberFuncPtrs::qqq2(short (Funcs::* const *& qq2)(bool)) const { return 0; } +int MemberFuncPtrs::qqq3(short (Funcs::* *& qq3)(bool)) const { return 0; } +int MemberFuncPtrs::qqq4(short (Funcs::* *const& qq4)(bool)) const { return 0; } +int MemberFuncPtrs::qqq5(short (Funcs::* & qq5)(bool)) const { return 0; } +int MemberFuncPtrs::qqq6(short (Funcs::* const qq6)(bool)) const { return 0; } +int MemberFuncPtrs::qqq7(short (Funcs::* const& qq7)(bool)) const { return 0; } + +// member non-const function pointer variables +short (Funcs::* pp1)(bool) = &Funcs::FF; + +short (Funcs::* const * extra2)(bool) = &pp1; +short (Funcs::* * extra3)(bool) = &pp1; +short (Funcs::* *const extra4)(bool) = &pp1; + +short (Funcs::* const *& pp2)(bool) = extra2; +short (Funcs::* *& pp3)(bool) = extra3; +short (Funcs::* *const& pp4)(bool) = extra4; +short (Funcs::* & pp5)(bool) = pp1; +short (Funcs::* const pp6)(bool) = &Funcs::FF; +short (Funcs::* const& pp7)(bool) = pp1; + +// member const function pointer variables +short (Funcs::* cc1)(bool) const = &Funcs::CC; + +short (Funcs::* const * ccextra2)(bool) const = &cc1; +short (Funcs::* * ccextra3)(bool) const = &cc1; +short (Funcs::* *const ccextra4)(bool) const = &cc1; + +short (Funcs::* const *& cc2)(bool) const = ccextra2; +short (Funcs::* *& cc3)(bool) const = ccextra3; +short (Funcs::* *const& cc4)(bool) const = ccextra4; +short (Funcs::* & cc5)(bool) const = cc1; +short (Funcs::* const cc6)(bool) const = &Funcs::CC; +short (Funcs::* const& cc7)(bool) const = cc1; +%} diff --git a/Examples/test-suite/member_pointer.i b/Examples/test-suite/member_pointer.i index fe454302a..e3b4f85ab 100644 --- a/Examples/test-suite/member_pointer.i +++ b/Examples/test-suite/member_pointer.i @@ -44,17 +44,22 @@ public: virtual double perimeter(void); }; +/* Typedef */ +typedef double (Shape::*PerimeterFunc_td)(void); + extern double do_op(Shape *s, double (Shape::*m)(void)); +extern double do_op_td(Shape *s, PerimeterFunc_td m); /* Functions that return member pointers */ extern double (Shape::*areapt())(void); extern double (Shape::*perimeterpt())(void); +extern PerimeterFunc_td perimeterpt_td(); /* Global variables that are member pointers */ extern double (Shape::*areavar)(void); extern double (Shape::*perimetervar)(void); - +extern PerimeterFunc_td perimetervar_td; %} %{ @@ -88,6 +93,10 @@ double do_op(Shape *s, double (Shape::*m)(void)) { return (s->*m)(); } +double do_op_td(Shape *s, PerimeterFunc_td m) { + return (s->*m)(); +} + double (Shape::*areapt())(void) { return &Shape::area; } @@ -96,9 +105,14 @@ double (Shape::*perimeterpt())(void) { return &Shape::perimeter; } +PerimeterFunc_td perimeterpt_td() { + return &Shape::perimeter; +} + /* Member pointer variables */ double (Shape::*areavar)(void) = &Shape::area; double (Shape::*perimetervar)(void) = &Shape::perimeter; +PerimeterFunc_td perimetervar_td = &Shape::perimeter; %} diff --git a/Examples/test-suite/member_pointer_const.i b/Examples/test-suite/member_pointer_const.i new file mode 100644 index 000000000..4af712f7f --- /dev/null +++ b/Examples/test-suite/member_pointer_const.i @@ -0,0 +1,149 @@ +%module member_pointer_const +// Same as member_pointer.i but using member pointer const functions + +%{ +#if defined(__SUNPRO_CC) +#pragma error_messages (off, badargtype2w) /* Formal argument ... is being passed extern "C" ... */ +#pragma error_messages (off, wbadinit) /* Using extern "C" ... to initialize ... */ +#pragma error_messages (off, wbadasg) /* Assigning extern "C" ... */ +#endif +%} + +%inline %{ +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + }; + double x, y; + double *z; + + void move(double dx, double dy); + virtual double area(void) const = 0; + virtual double perimeter(void) const = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { }; + virtual double area(void) const; + virtual double perimeter(void) const; +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { }; + virtual double area(void) const; + virtual double perimeter(void) const; +}; + +/* Typedef */ +typedef double (Shape::*PerimeterFunc_td)(void) const; + +extern double do_op(Shape *s, double (Shape::*m)(void) const); +extern double do_op_td(Shape *s, PerimeterFunc_td m); + +/* Functions that return member pointers */ + +extern double (Shape::*areapt())(void) const; +extern double (Shape::*perimeterpt())(void) const; +extern PerimeterFunc_td perimeterpt_td(); + +/* Global variables that are member pointers */ +extern double (Shape::*areavar)(void) const; +extern double (Shape::*perimetervar)(void) const; +extern PerimeterFunc_td perimetervar_td; +%} + +%{ +# define SWIG_M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area(void) const { + return SWIG_M_PI*radius*radius; +} + +double Circle::perimeter(void) const { + return 2*SWIG_M_PI*radius; +} + +double Square::area(void) const { + return width*width; +} + +double Square::perimeter(void) const { + return 4*width; +} + +double do_op(Shape *s, double (Shape::*m)(void) const) { + return (s->*m)(); +} + +double do_op_td(Shape *s, PerimeterFunc_td m) { + return (s->*m)(); +} + +double (Shape::*areapt())(void) const { + return &Shape::area; +} + +double (Shape::*perimeterpt())(void) const { + return &Shape::perimeter; +} + +PerimeterFunc_td perimeterpt_td() { + return &Shape::perimeter; +} + +/* Member pointer variables */ +double (Shape::*areavar)(void) const = &Shape::area; +double (Shape::*perimetervar)(void) const = &Shape::perimeter; +PerimeterFunc_td perimetervar_td = &Shape::perimeter; +%} + + +/* Some constants */ +%constant double (Shape::*AREAPT)(void) const = &Shape::area; +%constant double (Shape::*PERIMPT)(void) const = &Shape::perimeter; +%constant double (Shape::*NULLPT)(void) const = 0; + +/* +%inline %{ + struct Funktions { + void retByRef(int & (*d)(double)) {} + }; + void byRef(int & (Funktions::*d)(double)) {} +%} +*/ + +%inline %{ + +struct Funktions { + int addByValue(const int &a, int b) const { return a+b; } + int * addByPointer(const int &a, int b) const { static int val; val = a+b; return &val; } + int & addByReference(const int &a, int b) const { static int val; val = a+b; return val; } +}; + +int call1(int (Funktions::*d)(const int &, int) const, int a, int b) { Funktions f; return (f.*d)(a, b); } +//int call2(int * (Funktions::*d)(const int &, int) const, int a, int b) { Funktions f; return *(f.*d)(a, b); } +//int call3(int & (Funktions::*d)(const int &, int) const, int a, int b) { Funktions f; return (f.*d)(a, b); } +%} + +%constant int (Funktions::*ADD_BY_VALUE)(const int &, int) const = &Funktions::addByValue; +//%constant int * (Funktions::*ADD_BY_POINTER)(const int &, int) const = &Funktions::addByPointer; +//%constant int & (Funktions::*ADD_BY_REFERENCE)(const int &, int) const = &Funktions::addByReference; diff --git a/Examples/test-suite/minherit2.i b/Examples/test-suite/minherit2.i index 7d470d30e..2baea6495 100644 --- a/Examples/test-suite/minherit2.i +++ b/Examples/test-suite/minherit2.i @@ -17,8 +17,8 @@ #if defined(SWIGCSHARP) #define javaclassmodifiers csclassmodifiers #define javabody csbody -#define javafinalize csfinalize -#define javadestruct csdestruct +#define javafinalize csdispose +#define javadestruct csdisposing #define javaout csout #define javainterfaces csinterfaces #define javabase csbase diff --git a/Examples/test-suite/multiple_inheritance_shared_ptr.i b/Examples/test-suite/multiple_inheritance_shared_ptr.i index 5a08e5e6e..3c061e1a9 100644 --- a/Examples/test-suite/multiple_inheritance_shared_ptr.i +++ b/Examples/test-suite/multiple_inheritance_shared_ptr.i @@ -50,9 +50,9 @@ %shared_ptr(Space::Bottom3) %include "swiginterface.i" -SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(SWIGEMPTYHACK, Space::ABase1) -SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(SWIGEMPTYHACK, Space::CBase1) -SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(SWIGEMPTYHACK, Space::CBase2) +SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(, Space::ABase1) +SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(, Space::CBase1) +SWIG_SHARED_PTR_INTERFACE_TYPEMAPS(, Space::CBase2) %interface_impl(Space::ABase1) %interface_impl(Space::CBase1) %interface_impl(Space::CBase2) diff --git a/Examples/test-suite/multivalue.i b/Examples/test-suite/multivalue.i index 59f3d7643..3bc3471a1 100644 --- a/Examples/test-suite/multivalue.i +++ b/Examples/test-suite/multivalue.i @@ -11,14 +11,14 @@ back to this behavior, use: */ void divide_l(int a, int b, int *OUTPUT, int *OUTPUT); -/* Multiple values as vectors. By issueing: */ +/* Multiple values as vectors. By issuing: */ %values_as_vector; /* vectors instead of lists will be used. */ void divide_v(int a, int b, int *OUTPUT, int *OUTPUT); /* Multiple values for multiple-value continuations. - (This is the most elegant way.) By issueing: */ + (This is the most elegant way.) By issuing: */ %multiple_values; /* multiple values are passed to the multiple-value continuation, as created by `call-with-values' or the @@ -26,6 +26,11 @@ void divide_v(int a, int b, int *OUTPUT, int *OUTPUT); void divide_mv(int a, int b, int *OUTPUT, int *OUTPUT); +#else +%include "typemaps.i" +void divide_l(int a, int b, int *OUTPUT, int *OUTPUT); +void divide_v(int a, int b, int *OUTPUT, int *OUTPUT); +void divide_mv(int a, int b, int *OUTPUT, int *OUTPUT); #endif %{ @@ -49,4 +54,3 @@ void divide_mv(int a, int b, int *quotient_p, int *remainder_p) } %} - diff --git a/Examples/test-suite/mzscheme/Makefile.in b/Examples/test-suite/mzscheme/Makefile.in index 3e15f8610..6a8ef74e4 100644 --- a/Examples/test-suite/mzscheme/Makefile.in +++ b/Examples/test-suite/mzscheme/Makefile.in @@ -10,10 +10,70 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ +FAILING_CPP_TESTS = \ +allowexcept \ +apply_strings \ +arrays_dimensionless \ +arrays_global \ +char_strings \ +chartest \ +class_scope_weird \ +constant_pointers \ +cpp_basic \ +cpp_enum \ +curiously_recurring_template_pattern \ +default_arg_expressions \ +default_constructor \ +derived_nested \ +director_ignore \ +enum_thorough \ +extend \ +friends \ +global_scope_types \ +inherit_member \ +li_attribute \ +li_attribute_template \ +li_boost_shared_ptr \ +li_std_combinations \ +li_std_map \ +li_std_pair \ +li_std_pair_using \ +li_std_string \ +li_std_vector \ +li_windows \ +member_funcptr_galore \ +member_pointer \ +member_pointer_const \ +memberin_extend \ +namespace_spaces \ +naturalvar \ +naturalvar_more \ +nested_class \ +nested_template_base \ +ordering \ +preproc_constants \ +samename \ +static_const_member \ +string_constants \ +template_default2 \ +template_specialization_defarg \ +template_typemaps \ +typemap_variables \ +valuewrapper_opaque \ + +FAILING_C_TESTS = \ +enums \ +integers \ +preproc_constants_c \ +preproc_line_file \ + +FAILING_MULTI_CPP_TESTS = \ +multi_import \ + include $(srcdir)/../common.mk # Overridden variables here -# none! +SWIGOPT += -w524 # Suppress SWIGWARN_LANG_EXPERIMENTAL warning # Custom tests - tests with additional commandline options # none! diff --git a/Examples/test-suite/mzscheme/name_runme.scm b/Examples/test-suite/mzscheme/name_runme.scm index 1782c6481..94df9131d 100644 --- a/Examples/test-suite/mzscheme/name_runme.scm +++ b/Examples/test-suite/mzscheme/name_runme.scm @@ -1,7 +1,7 @@ ;; The SWIG modules have "passive" Linkage, i.e., they don't generate ;; Guile modules (namespaces) but simply put all the bindings into the ;; current module. That's enough for such a simple test. -(load-extension "./name.so") +(load-extension "name.so") (foo-2) bar-2 diff --git a/Examples/test-suite/mzscheme/unions_runme.scm b/Examples/test-suite/mzscheme/unions_runme.scm index c44847cfc..1c39cb94c 100644 --- a/Examples/test-suite/mzscheme/unions_runme.scm +++ b/Examples/test-suite/mzscheme/unions_runme.scm @@ -25,13 +25,15 @@ (if (not (= Jill1 200)) (begin (display "Runtime test 1 failed.") - (exit 1)))) + (exit 1)) + (void))) (let ((Num1 (EmbeddedUnionTest-number-get eut))) (if (not (= Num1 1)) (begin (display "Runtime test 2 failed.") - (exit 1)))) + (exit 1)) + (void))) ;; that should do diff --git a/Examples/test-suite/name_warnings.i b/Examples/test-suite/name_warnings.i index 3455c03bf..0b62ec5d7 100644 --- a/Examples/test-suite/name_warnings.i +++ b/Examples/test-suite/name_warnings.i @@ -40,9 +40,7 @@ namespace std #endif virtual ~A() {} -#ifndef SWIGGO // func is a keyword in Go. - virtual int func() = 0; -#endif + virtual int funk() = 0; private: typedef complex False; }; diff --git a/Examples/test-suite/namespace_chase.i b/Examples/test-suite/namespace_chase.i new file mode 100644 index 000000000..5e3921d0d --- /dev/null +++ b/Examples/test-suite/namespace_chase.i @@ -0,0 +1,36 @@ +%module namespace_chase + +%inline %{ + namespace Space1A { + struct Struct1A {}; + namespace Space1B { + struct Struct1B {}; + namespace Space1C { + struct Struct1C {}; + } + } + } + namespace Space2A { + using namespace Space1A; + namespace Space2B { + using namespace Space1B; + namespace Space2C { + using namespace Space1C; + } + } + } + namespace Space3 { + using namespace Space2A; + void sss3a(Space1A::Struct1A, Space1A::Space1B::Struct1B, Space1A::Space1B::Space1C::Struct1C) {} + void sss3b(Struct1A, Space1B::Struct1B, Space1B::Space1C::Struct1C) {} + // To fix: the last two parameters below fail and result in SWIGTYPE_ types instead of proxy classes + void sss3c(Space2A::Struct1A, Space2A::Space1B::Struct1B, Space2A::Space1B::Space1C::Struct1C) {} + } + namespace Space4 { + using namespace Space2A; + using namespace Space2A::Space2B; + using namespace Space2A::Space2B::Space2C; + void sss4a(Struct1A, Struct1B, Space2C::Struct1C) {} + void sss4b(Struct1A, Struct1B, Struct1C) {} + } +%} diff --git a/Examples/test-suite/namespace_template.i b/Examples/test-suite/namespace_template.i index a36abb19b..8a4b6dca9 100644 --- a/Examples/test-suite/namespace_template.i +++ b/Examples/test-suite/namespace_template.i @@ -2,10 +2,10 @@ %module namespace_template -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) vector; /* Ruby, wrong class name */ -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test2::vector; /* Ruby, wrong class name */ -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test3::vector; /* Ruby, wrong class name */ -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) vector; /* Ruby, wrong class name */ +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector; /* Ruby, wrong class name */ +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector; /* Ruby, wrong class name */ +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector; /* Ruby, wrong class name */ +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector; /* Ruby, wrong class name */ %{ #ifdef max @@ -23,20 +23,9 @@ namespace test { char * blah(T x) { return (char *) "vector::blah"; } + void vectoruse(vector a, test::vector b) {} }; } - -namespace test2 { - using namespace test; -} - -namespace test3 { - using test::max; - using test::vector; -} - -using namespace test2; -namespace T4 = test; %} namespace test { @@ -48,6 +37,7 @@ namespace test { char * blah(T x) { return (char *) "vector::blah"; } + void vectoruse(vector a, test::vector b) {} }; } @@ -55,30 +45,26 @@ using namespace test; %template(maxint) max; %template(vectorint) vector; -namespace test2 { - using namespace test; +namespace test { %template(maxshort) max; %template(vectorshort) vector; } -namespace test3 { - using test::max; - using test::vector; +namespace test { %template(maxlong) max; %template(vectorlong) vector; } %inline %{ -namespace test4 { - using namespace test; - typedef int Integer; +namespace test { + typedef char Char; } %} -namespace test4 { - %template(maxInteger) max; - %template(vectorInteger) vector; +namespace test { + %template(maxchar) max; + %template(vectorchar) vector; } diff --git a/Examples/test-suite/namespace_typemap.i b/Examples/test-suite/namespace_typemap.i index 7f474bd9c..9c74715f0 100644 --- a/Examples/test-suite/namespace_typemap.i +++ b/Examples/test-suite/namespace_typemap.i @@ -50,7 +50,7 @@ namespace test { PyComplex_ImagAsDouble($input)); } else { PyErr_SetString(PyExc_TypeError,"Expected test_complex.\n"); - return NULL; + SWIG_fail; } } %typemap(freearg) test::test_complex * { @@ -242,7 +242,7 @@ namespace Split { $1 = PyInt_AsLong($input); if ($1 < 0) { PyErr_SetString(PyExc_ValueError,"domain error\n"); - return NULL; + SWIG_fail; } } #endif diff --git a/Examples/test-suite/native_directive.i b/Examples/test-suite/native_directive.i new file mode 100644 index 000000000..d08c9a954 --- /dev/null +++ b/Examples/test-suite/native_directive.i @@ -0,0 +1,43 @@ +%module native_directive + +%{ +#include +int alpha_count(const char *instring) { + int count = 0; + const char *s = instring; + while (s && *s) { + if (isalpha((int)*s)) + count++; + s++; + }; + return count; +} +%} + +%inline %{ +int CountAlphas(const char *instring) { + return alpha_count(instring); +} +%} + +// Languages that support %native should code up language specific implementations below + +#if defined(SWIGJAVA) +%native(CountAlphaCharacters) int alpha_count(const char *inputString); +%{ +extern "C" JNIEXPORT jint JNICALL Java_native_1directive_native_1directiveJNI_CountAlphaCharacters(JNIEnv *jenv, jclass jcls, jstring instring) { + jint jresult = 0 ; + (void)jcls; + + if (instring) { + const char *s = (char *)jenv->GetStringUTFChars(instring, 0); + if (s) { + jresult = (jint)alpha_count(s); + jenv->ReleaseStringUTFChars(instring, s); + } + } + return jresult; +} +%} +#endif + diff --git a/Examples/test-suite/nested.i b/Examples/test-suite/nested.i index 216ee4224..6c4ffe34a 100644 --- a/Examples/test-suite/nested.i +++ b/Examples/test-suite/nested.i @@ -44,42 +44,6 @@ struct OuterStructNamed { %} -#if !defined(SWIGSCILAB) - -%inline %{ - -struct OuterStructUnnamed { - struct { - double xx; - } inner_struct_unnamed; - union { - double yy; - int zz; - } inner_union_unnamed; -}; - -typedef struct OuterStruct { - union { - - struct outer_nested_struct { - union inner_nested_union { -#define BAD_STYLE 1 - int red; - struct TestStruct green; - } InnerNestedUnion; - - struct inner_nested_struct { - int blue; - } InnerNestedStruct; - } OuterNestedStruct; - - } EmbeddedUnion; -} OuterStruct; - -%} - -#else - %inline %{ struct OutStUnnamed { @@ -112,6 +76,51 @@ typedef struct OutSt { %} -#endif +%inline %{ + typedef struct { + union x_union { + int x; + } duplicate_p; + } x_t; + + typedef struct { + union y_union { + int y; + } duplicate_p; + } y_t; + + typedef struct A { + union a_union { + int a; + } duplicate_p; + } a_t; + + typedef struct B { + union b_union { + int b; + } duplicate_p; + } b_t; + + typedef struct { + union { + int c; + } duplicate_p; + } c_t; + + typedef struct { + union { + int d; + } duplicate_p; + } d_t; + + void set_union_values(int startval, x_t *x, y_t *y, a_t *a, b_t *b, c_t *c, d_t *d) { + x->duplicate_p.x = startval++; + y->duplicate_p.y = startval++; + a->duplicate_p.a = startval++; + b->duplicate_p.b = startval++; + c->duplicate_p.c = startval++; + d->duplicate_p.d = startval++; + } +%} diff --git a/Examples/test-suite/nested_in_template.i b/Examples/test-suite/nested_in_template.i new file mode 100644 index 000000000..81d5b6289 --- /dev/null +++ b/Examples/test-suite/nested_in_template.i @@ -0,0 +1,34 @@ +%module nested_in_template + +#if !defined(SWIGCSHARP) && !defined(SWIGJAVA) +%feature("flatnested"); +#endif + +%inline %{ +template +struct OuterTemplate; + +template <> +struct OuterTemplate<1> +{ + struct AbstractBase + { + virtual bool IsSameAs(const AbstractBase& other) const = 0; + virtual ~AbstractBase() {} + }; + + struct ConcreteDerived : AbstractBase + { + ConcreteDerived() : m_value(0) {} + explicit ConcreteDerived(int value) : m_value(value) {} + + virtual bool IsSameAs(const AbstractBase& other) const { + return m_value == static_cast(other).m_value; + } + + int m_value; + }; +}; +%} + +%template(OuterTemplate1) OuterTemplate<1>; diff --git a/Examples/test-suite/nested_inheritance_interface.i b/Examples/test-suite/nested_inheritance_interface.i new file mode 100644 index 000000000..f8335c0af --- /dev/null +++ b/Examples/test-suite/nested_inheritance_interface.i @@ -0,0 +1,20 @@ +%module nested_inheritance_interface + +%warnfilter(SWIGWARN_RUBY_MULTIPLE_INHERITANCE, + SWIGWARN_D_MULTIPLE_INHERITANCE, + SWIGWARN_PHP_MULTIPLE_INHERITANCE); /* languages not supporting multiple inheritance or %interface */ + +#if defined(SWIGJAVA) || defined(SWIGCSHARP) +%include "swiginterface.i" +%interface(IA) +#endif + +#if !defined(SWIGCSHARP) && !defined(SWIGJAVA) +%feature ("flatnested"); +#endif + + +%inline %{ +struct IA {}; +struct B { struct N : IA {}; }; +%} diff --git a/Examples/test-suite/nested_structs.i b/Examples/test-suite/nested_structs.i index c70924958..48bd9f2b9 100644 --- a/Examples/test-suite/nested_structs.i +++ b/Examples/test-suite/nested_structs.i @@ -12,6 +12,10 @@ #endif +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + // bug #491476 %inline %{ struct Outer { diff --git a/Examples/test-suite/nested_template_base.i b/Examples/test-suite/nested_template_base.i index 0b0272224..4d99e8af5 100644 --- a/Examples/test-suite/nested_template_base.i +++ b/Examples/test-suite/nested_template_base.i @@ -1,5 +1,9 @@ %module nested_template_base +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %inline %{ template class OuterT { public: diff --git a/Examples/test-suite/newobject3.i b/Examples/test-suite/newobject3.i new file mode 100644 index 000000000..ef12cd401 --- /dev/null +++ b/Examples/test-suite/newobject3.i @@ -0,0 +1,25 @@ +/** + * Regression test for PHP bug: https://sourceforge.net/p/swig/bugs/1350/ + */ + +%module newobject3 + +%newobject factory::create; +%inline %{ +class Product {}; +class factory { +public: + Product * create(short id, short type = 0); + Product * create(const char * name, short type = 0); +}; +%} + +%{ +Product * factory::create(short id, short type) { + return (id && type >= 0) ? new Product : NULL; +} + +Product * factory::create(const char * name, short type) { + return (name && type >= 0) ? new Product : NULL; +} +%} diff --git a/Examples/test-suite/null_pointer.i b/Examples/test-suite/null_pointer.i index 0da827f99..f40d6929f 100644 --- a/Examples/test-suite/null_pointer.i +++ b/Examples/test-suite/null_pointer.i @@ -1,11 +1,9 @@ %module null_pointer -%warnfilter(SWIGWARN_PARSE_KEYWORD) func; // 'func' is a Go keyword, renamed as 'Xfunc' - %inline { struct A {}; - bool func(A* a) { + bool funk(A* a) { return !a; } diff --git a/Examples/test-suite/ocaml/Makefile.in b/Examples/test-suite/ocaml/Makefile.in index ecdf32e9f..775b1ea71 100644 --- a/Examples/test-suite/ocaml/Makefile.in +++ b/Examples/test-suite/ocaml/Makefile.in @@ -3,7 +3,9 @@ ####################################################################### LANGUAGE = ocaml -OCAMLC = @OCAMLC@ +OCAMLP4WHERE =`$(COMPILETOOL) @CAMLP4@ -where` +OCC =$(COMPILETOOL) @OCAMLC@ +OCAMLPP = -pp "camlp4o ./swigp4.cmo" VARIANT = _static SCRIPTSUFFIX = _runme.ml @@ -11,67 +13,94 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -C_TEST_CASES = +FAILING_CPP_TESTS = \ +allprotected \ +apply_signed_char \ +apply_strings \ +cpp_enum \ +default_constructor \ +director_binary_string \ +director_enum \ +director_primitives \ +director_redefined \ +director_string \ +enum_thorough \ +li_windows \ +member_pointer_const \ +preproc_constants \ +smart_pointer_inherit \ + +FAILING_C_TESTS = \ +enums \ +preproc_constants_c \ + +CPP_TEST_CASES += \ + inout \ + +C_TEST_CASES += \ + multivalue \ + +ml_runme = $(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) run_testcase = \ - if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) -a \ - -f $(top_srcdir)/Examples/test-suite/$*.list ] ; then \ - $(COMPILETOOL) $(OCAMLC) -c $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ - $(COMPILETOOL) $(OCAMLC) swig.cmo -custom -g -cc '$(CXX)' -o runme `cat $(top_srcdir)/Examples/test-suite/$(*).list | sed -e 's/\(.*\)/\1_wrap.o \1.cmo/g'`&& $(RUNTOOL) ./runme; \ - elif [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ - $(COMPILETOOL) $(OCAMLC) -c $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ - $(COMPILETOOL) $(OCAMLC) swig.cmo -custom -g -cc '$(CXX)' -o runme $(srcdir)/$(*).cmo $(srcdir)/$(*)_runme.cmo $(srcdir)/$(*)_wrap.o && \ - $(RUNTOOL) ./runme; \ + if [ -f $(srcdir)/$(ml_runme) ]; then \ + if [ $(srcdir) != . ]; then \ + cp $(srcdir)/$(ml_runme) $(ml_runme); \ + fi ; \ + $(OCC) $(OCAMLPP) -c $(ml_runme) && \ + if [ -f $(top_srcdir)/Examples/test-suite/$*.list ]; then \ + $(OCC) swig.cmo -custom -g -cc '$(CXX)' -o $*_runme `cat $(top_srcdir)/Examples/test-suite/$(*).list | sed -e 's/\(.*\)/\1_wrap.o \1.cmo/g'`&& $(RUNTOOL) ./$*_runme; \ + else \ + $(OCC) swig.cmo -custom -g -cc '$(CXX)' -o $*_runme $(*).cmo $(*)_runme.cmo $(*)_wrap.o && $(RUNTOOL) ./$*_runme; \ + fi ; \ fi ; -check_quant: - : > testing - : > success - $(MAKE) check - echo "Failed:" > results - diff testing success | sed 's/^< //p;d' >> results - echo "Success:" >> results - cat success >> results - include $(srcdir)/../common.mk # Overridden variables here -# none! +SWIGOPT += -w524 # Suppress SWIGWARN_LANG_EXPERIMENTAL warning # Custom tests - tests with additional commandline options # none! # Rules for the different types of tests %.cpptest: - echo $@ >> testing $(setup) +$(swig_and_compile_cpp) $(run_testcase) - if [ -f $(@:%.cpptest=%_wrap.o) ] ; then \ - echo $@ >> success ; \ - fi %.ctest: - echo $@ >> testing $(setup) +$(swig_and_compile_c) $(run_testcase) - if [ -f $(@:%.ctest=%_wrap.o) ] ; then \ - echo $@ >> success ; \ - fi %.multicpptest: - echo $@ >> testing +$(swig_and_compile_multi_cpp) $(setup) $(run_testcase) - if [ -f $(@:%.multicpptest=%_runtime_wrap.o) ] ; then \ - echo $@ >> success ; \ - fi + +swig.cmi: + env SWIG_LIB=$(SWIG_LIB_DIR) $(SWIGEXE) -ocaml -co swig.mli + $(OCC) -c swig.mli +swig.cmo: + env SWIG_LIB=$(SWIG_LIB_DIR) $(SWIGEXE) -ocaml -co swig.ml + $(OCC) -c swig.ml +swigp4.cmi: + env SWIG_LIB=$(SWIG_LIB_DIR) $(SWIGEXE) -ocaml -co swigp4.ml + $(OCC) -I $(OCAMLP4WHERE) -pp "camlp4o pa_extend.cmo q_MLast.cmo" -c swigp4.ml +extra_objects: swig.cmi swig.cmo swigp4.cmi + +$(C_TEST_CASES:=.ctest): extra_objects +$(CPP_TEST_CASES:=.cpptest): extra_objects +$(MULTI_CPP_TEST_CASES:=.multicpptest): extra_objects # Clean %.clean: - @rm -f $*.ml $*.mli; + @rm -f $*.ml $*.mli $*_runme; + @if test $(srcdir) != .; then rm -f $(ml_runme); fi clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' ocaml_clean + rm -f clientdata_prop_a.ml clientdata_prop_b.ml import_stl_a.ml import_stl_b.ml + rm -f imports_a.ml imports_b.ml mod_a.ml mod_b.ml multi_import_a.ml + rm -f multi_import_b.ml packageoption_a.ml packageoption_b.ml packageoption_c.ml diff --git a/Examples/test-suite/ocaml/abstract_access_runme.ml b/Examples/test-suite/ocaml/abstract_access_runme.ml new file mode 100644 index 000000000..77ad88667 --- /dev/null +++ b/Examples/test-suite/ocaml/abstract_access_runme.ml @@ -0,0 +1,5 @@ +open Swig +open Abstract_access + +let d = new_D '() +let _ = assert ((d -> "do_x" () as int) = 1) diff --git a/Examples/test-suite/ocaml/abstract_typedef2_runme.ml b/Examples/test-suite/ocaml/abstract_typedef2_runme.ml new file mode 100644 index 000000000..64aa19b91 --- /dev/null +++ b/Examples/test-suite/ocaml/abstract_typedef2_runme.ml @@ -0,0 +1,4 @@ +open Swig +open Abstract_typedef2 + +let a = new_A_UF '() diff --git a/Examples/test-suite/ocaml/abstract_typedef_runme.ml b/Examples/test-suite/ocaml/abstract_typedef_runme.ml new file mode 100644 index 000000000..728c25b3b --- /dev/null +++ b/Examples/test-suite/ocaml/abstract_typedef_runme.ml @@ -0,0 +1,6 @@ +open Swig +open Abstract_typedef + +let e = new_Engine '() +let a = new_A '() +let _ = assert ((a -> "write" (e) as bool) = true) diff --git a/Examples/test-suite/ocaml/abstract_virtual_runme.ml b/Examples/test-suite/ocaml/abstract_virtual_runme.ml new file mode 100644 index 000000000..60f4f4ab7 --- /dev/null +++ b/Examples/test-suite/ocaml/abstract_virtual_runme.ml @@ -0,0 +1,5 @@ +open Swig +open Abstract_virtual + +let d = new_D '() +let e = new_E '() diff --git a/Examples/test-suite/ocaml/aggregate_runme.ml b/Examples/test-suite/ocaml/aggregate_runme.ml new file mode 100644 index 000000000..f8fff0f30 --- /dev/null +++ b/Examples/test-suite/ocaml/aggregate_runme.ml @@ -0,0 +1,15 @@ +open Swig +open Aggregate + +let _ = + assert((_move (_UP '()) as int) = (_UP '() as int)); + assert((_move (_DOWN '()) as int) = (_DOWN '() as int)); + assert((_move (_LEFT '()) as int) = (_LEFT '() as int)); + assert((_move (_RIGHT '()) as int) = (_RIGHT '() as int)); +;; + +let _ = + try + _move(0 to int) + with Failure _ -> exit 0 +let _ = raise (Failure "0 test failed") diff --git a/Examples/test-suite/ocaml/allowexcept_runme.ml b/Examples/test-suite/ocaml/allowexcept_runme.ml new file mode 100644 index 000000000..9c8c9de7f --- /dev/null +++ b/Examples/test-suite/ocaml/allowexcept_runme.ml @@ -0,0 +1,7 @@ +open Swig +open Allowexcept + +let _ = + assert (_global_variable '() = C_void); + assert (_Foo_static_member_variable '() = C_void) +;; diff --git a/Examples/test-suite/ocaml/cast_operator_runme.ml b/Examples/test-suite/ocaml/cast_operator_runme.ml new file mode 100644 index 000000000..99c390a19 --- /dev/null +++ b/Examples/test-suite/ocaml/cast_operator_runme.ml @@ -0,0 +1,5 @@ +open Swig +open Cast_operator + +let a = new_A '() +let _ = assert ((a -> "tochar" () as string) = "hi") diff --git a/Examples/test-suite/ocaml/catches_runme.ml b/Examples/test-suite/ocaml/catches_runme.ml new file mode 100644 index 000000000..ab38e635d --- /dev/null +++ b/Examples/test-suite/ocaml/catches_runme.ml @@ -0,0 +1,39 @@ +open Swig +open Catches + +let _ = + try + ignore (_test_catches '(1)); assert false + with Failure s -> + assert (s = "C++ int exception thrown, value: 1") + + try + ignore (_test_catches '(2)); assert false + with Failure s -> + assert (s = "two") + + try + ignore (_test_catches '(3)); assert false + with Failure s -> + assert (s = "C++ ThreeException const & exception thrown") + + try + ignore (_test_exception_specification '(1)); assert false + with Failure s -> + assert (s = "C++ int exception thrown, value: 1") + + try + ignore (_test_exception_specification '(2)); assert false + with Failure s -> + assert (s = "unknown exception") + + try + ignore (_test_exception_specification '(3)); assert false + with Failure s -> + assert (s = "unknown exception") + + try + ignore (_test_catches_all '(1)); assert false + with Failure s -> + assert (s = "unknown exception") +;; diff --git a/Examples/test-suite/ocaml/char_binary_runme.ml b/Examples/test-suite/ocaml/char_binary_runme.ml new file mode 100644 index 000000000..2d3aba1b3 --- /dev/null +++ b/Examples/test-suite/ocaml/char_binary_runme.ml @@ -0,0 +1,24 @@ +open Swig +open Char_binary + +let _ = + let t = new_Test '() in + assert (t -> strlen ("hile") as int = 4); + assert (t -> ustrlen ("hile") as int = 4); + assert (t -> strlen ("hil\x00") as int = 4); + assert (t -> ustrlen ("hil\x00") as int = 4); + + let pc = _new_pchar '(5) in + assert (_pchar_setitem '(pc, 0, 'h') = C_void); + assert (_pchar_setitem '(pc, 1, 'o') = C_void); + assert (_pchar_setitem '(pc, 2, 'l') = C_void); + assert (_pchar_setitem '(pc, 3, 'a') = C_void); + assert (_pchar_setitem '(pc, 4, 0) = C_void); + assert (t -> strlen (pc) as int = 4); + assert (t -> ustrlen (pc) as int = 4); + ignore (_var_pchar '(pc)); + assert (_var_pchar '() as string = "hola"); + ignore (_var_namet '(pc)); + assert (_var_namet '() as string = "hola"); + _delete_pchar(pc) +;; diff --git a/Examples/test-suite/ocaml/char_constant_runme.ml b/Examples/test-suite/ocaml/char_constant_runme.ml new file mode 100644 index 000000000..9d0ce6903 --- /dev/null +++ b/Examples/test-suite/ocaml/char_constant_runme.ml @@ -0,0 +1,16 @@ +open Swig +open Char_constant + +let _ = + assert (_CHAR_CONSTANT '() as char = 'x'); + assert (_STRING_CONSTANT '() as string = "xyzzy"); + assert (_ESC_CONST '() as char = '\x01'); + assert (_NULL_CONST '() as char = '\x00'); + assert (_SPECIALCHARA '() as char = 'A'); + assert (_SPECIALCHARB '() as char = 'B'); + assert (_SPECIALCHARC '() as char = 'C'); + assert (_SPECIALCHARD '() as char = 'D'); + assert (_SPECIALCHARE '() as char = 'E'); + assert (_ia '() as char = 'a'); + assert (_ib '() as char = 'b'); +;; diff --git a/Examples/test-suite/ocaml/chartest_runme.ml b/Examples/test-suite/ocaml/chartest_runme.ml new file mode 100644 index 000000000..3a2c81d03 --- /dev/null +++ b/Examples/test-suite/ocaml/chartest_runme.ml @@ -0,0 +1,25 @@ +open Swig +open Chartest + +let _ = + assert (_GetPrintableChar '() as char = 'a'); + assert (_GetUnprintableChar '() as char = '\127'); + assert (_printable_global_char '() as char = 'a'); + assert (_unprintable_global_char '() as char = '\127'); + assert (_globchar0 '() as char = '\x00'); + assert (_globchar1 '() as char = '\x01'); + assert (_globchar2 '() as char = '\n'); + assert (_globcharA '() as char = 'A'); + assert (_globcharB '() as char = 'B'); + assert (_globcharC '() as char = 'C'); + assert (_globcharD '() as char = 'D'); + assert (_globcharE '() as char = 'E'); + assert (_CharTestClass_memberchar0 '() as char = '\x00'); + assert (_CharTestClass_memberchar1 '() as char = '\x01'); + assert (_CharTestClass_memberchar2 '() as char = '\n'); + assert (_CharTestClass_membercharA '() as char = 'A'); + assert (_CharTestClass_membercharB '() as char = 'B'); + assert (_CharTestClass_membercharC '() as char = 'C'); + assert (_CharTestClass_membercharD '() as char = 'D'); + assert (_CharTestClass_membercharE '() as char = 'E'); +;; diff --git a/Examples/test-suite/ocaml/class_scope_weird_runme.ml b/Examples/test-suite/ocaml/class_scope_weird_runme.ml new file mode 100644 index 000000000..de7f457d4 --- /dev/null +++ b/Examples/test-suite/ocaml/class_scope_weird_runme.ml @@ -0,0 +1,6 @@ +open Swig +open Class_scope_weird + +let f = new_Foo (C_void) +let g = new_Foo (C_int 3) +let _ = assert (get_int ((invoke f) "bar" (C_int 3)) = 3) diff --git a/Examples/test-suite/ocaml/constover_runme.ml b/Examples/test-suite/ocaml/constover_runme.ml new file mode 100644 index 000000000..0ca2a5c01 --- /dev/null +++ b/Examples/test-suite/ocaml/constover_runme.ml @@ -0,0 +1,16 @@ +open Swig +open Constover + +let test_str = "test" to string +let _ = + assert ((_test (test_str) as string) = "test"); + assert ((_test_pconst (test_str) as string) = "test_pconst"); +;; + +let f = new_Foo '() +let _ = + assert ((f -> "test" (test_str) as string) = "test"); + assert ((f -> "test_pconst" (test_str) as string) = "test_pconst"); + assert ((f -> "test_constm" (test_str) as string) = "test_constmethod"); + assert ((f -> "test_pconstm" (test_str) as string) = "test_pconstmethod"); +;; diff --git a/Examples/test-suite/ocaml/constructor_rename_runme.ml b/Examples/test-suite/ocaml/constructor_rename_runme.ml new file mode 100644 index 000000000..5e5553838 --- /dev/null +++ b/Examples/test-suite/ocaml/constructor_rename_runme.ml @@ -0,0 +1,5 @@ +open Swig +open Constructor_rename + +let x = new_RenamedConstructor '() +let _ = assert ((x -> ":classof" () as string) = "Foo") diff --git a/Examples/test-suite/ocaml/conversion_runme.ml b/Examples/test-suite/ocaml/conversion_runme.ml new file mode 100644 index 000000000..8e4c19f2d --- /dev/null +++ b/Examples/test-suite/ocaml/conversion_runme.ml @@ -0,0 +1,9 @@ +open Swig +open Conversion + +let _ = + let bar = new_Bar '() in + assert (bar -> ":classof" () as string = "Bar"); + let foo = bar -> toFoo () in + assert (foo -> ":classof" () as string = "Foo"); +;; diff --git a/Examples/test-suite/ocaml/cpp_nodefault_runme.ml b/Examples/test-suite/ocaml/cpp_nodefault_runme.ml new file mode 100644 index 000000000..a0bd84071 --- /dev/null +++ b/Examples/test-suite/ocaml/cpp_nodefault_runme.ml @@ -0,0 +1,17 @@ +open Swig +open Cpp_nodefault + +let foo1 = new_Foo '(1, 2) +let _ = foo1 -> "[a]" (5) +let _ = assert ((foo1 -> "[a]" () as int) = 5) + +let foo2 = _create '(1, 2) +let _ = _consume '(foo1,foo2) + +let bar1 = new_Bar '() +let gvar = _gvar '() +let args = (C_list [ gvar ; foo2 ]) +let _ = bar1 -> "consume" (args) +let foo3 = bar1 -> "create" (1, 2) +let _ = foo3 -> "[a]" (6) +let _ = assert ((foo3 -> "[a]" () as int) = 6) diff --git a/Examples/test-suite/ocaml/cpp_static_runme.ml b/Examples/test-suite/ocaml/cpp_static_runme.ml new file mode 100644 index 000000000..9b04abced --- /dev/null +++ b/Examples/test-suite/ocaml/cpp_static_runme.ml @@ -0,0 +1,17 @@ +open Swig +open Cpp_static + +let _ = _StaticFunctionTest_static_func (C_void) +let _ = _StaticFunctionTest_static_func_2 (C_int 1) +let _ = _StaticFunctionTest_static_func_3 (C_list [C_int 1; C_int 2]) + +let _ = assert (get_int (_StaticMemberTest_static_int (C_void)) = 99) +let _ = _StaticMemberTest_static_int (C_int 10) +let _ = assert (get_int (_StaticMemberTest_static_int (C_void)) = 10) + +let _ = assert (get_int (_StaticBase_statty (C_void)) = 11) +let _ = assert (get_int (_StaticDerived_statty (C_void)) = 111) +let _ = _StaticBase_statty (C_int 22) +let _ = _StaticDerived_statty (C_int 222) +let _ = assert (get_int (_StaticBase_statty (C_void)) = 22) +let _ = assert (get_int (_StaticDerived_statty (C_void)) = 222) diff --git a/Examples/test-suite/ocaml/default_arg_values_runme.ml b/Examples/test-suite/ocaml/default_arg_values_runme.ml new file mode 100644 index 000000000..e9edcb9d9 --- /dev/null +++ b/Examples/test-suite/ocaml/default_arg_values_runme.ml @@ -0,0 +1,17 @@ +open Swig +open Default_arg_values + +let _ = + let d = new_Display '() in + assert (d -> draw1 () as float = 0.); + let arg = C_float 12. in + assert (d -> draw1 (arg) as float = 12.); + let arg = C_float 123. in + let p = _createPtr '(arg) in + assert (d -> draw2 () as float = 0.); + assert (d -> draw2 (p) as float = 123.); + assert (d -> bool0 () as bool = false); + assert (d -> bool1 () as bool = true); + assert (d -> mybool0 () as bool = false); + assert (d -> mybool1 () as bool = true) +;; diff --git a/Examples/test-suite/ocaml/default_args_runme.ml b/Examples/test-suite/ocaml/default_args_runme.ml new file mode 100644 index 000000000..1654b011f --- /dev/null +++ b/Examples/test-suite/ocaml/default_args_runme.ml @@ -0,0 +1,58 @@ +open Swig +open Default_args + +let _ = + assert (_anonymous '() as int = 7771); + assert (_anonymous '(1234) as int = 1234); + assert (_booltest '() as bool = true); + assert (_booltest '(true) as bool = true); + assert (_booltest '(false) as bool = false); + let ec = new_EnumClass '() in + assert (ec -> blah () as bool = true); + let de = new_DerivedEnumClass '() in + assert (de -> accelerate () = C_void); + let args = _SLOW '() in + assert (de -> accelerate (args) = C_void); + assert (_Statics_staticmethod '() as int = 60); + assert (_cfunc1 '(1) as float = 2.); + assert (_cfunc2 '(1) as float = 3.); + assert (_cfunc3 '(1) as float = 4.); + + let f = new_Foo '() in + assert (f -> newname () = C_void); + assert (f -> newname (1) = C_void); + (* TODO: There needs to be a more elegant way to pass NULL/nullptr. *) + let args = C_list [ C_int 2 ; C_ptr (0L, 0L) ] in + assert (f -> double_if_void_ptr_is_null (args) as int = 4); + assert (f -> double_if_void_ptr_is_null (3) as int = 6); + let args = C_list [ C_int 4 ; C_ptr (0L, 0L) ] in + assert (f -> double_if_handle_is_null (args) as int = 8); + assert (f -> double_if_handle_is_null (5) as int = 10); + let args = C_list [ C_int 6 ; C_ptr (0L, 0L) ] in + assert (f -> double_if_dbl_ptr_is_null (args) as int = 12); + assert (f -> double_if_dbl_ptr_is_null (7) as int = 14); + + let k = new_Klass '(22) in + let k2 = _Klass_inc (C_list [ C_int 100 ; k ]) in + assert (k2 -> "[val]" () as int = 122); + let k2 = _Klass_inc '(100) in + assert (k2 -> "[val]" () as int = 99); + let k2 = _Klass_inc '() in + assert (k2 -> "[val]" () as int = 0); + + assert (_seek '() = C_void); + assert (_seek (C_int64 10L) = C_void); + + assert (_slightly_off_square '(10) as int = 102); + assert (_slightly_off_square '() as int = 291); + + assert (_casts1 '() as char = '\x00'); + assert (_casts2 '() as string = "Hello"); + assert (_casts1 '("Ciao") as string = "Ciao"); + assert (_chartest1 '() as char = 'x'); + assert (_chartest2 '() as char = '\x00'); + assert (_chartest3 '() as char = '\x01'); + assert (_chartest4 '() as char = '\n'); + assert (_chartest5 '() as char = 'B'); + assert (_chartest6 '() as char = 'C'); +;; diff --git a/Examples/test-suite/ocaml/director_default_runme.ml b/Examples/test-suite/ocaml/director_default_runme.ml new file mode 100644 index 000000000..4fd655a00 --- /dev/null +++ b/Examples/test-suite/ocaml/director_default_runme.ml @@ -0,0 +1,25 @@ +open Swig +open Director_default + +let director_default_MyFoo ob meth args = + match meth with + "Msg" -> (match args with + | C_list [ msg ] -> C_string ("director_default_MyFoo-" ^ (msg as string)) + | _ -> raise (Failure "director_default_MyFoo::Msg()")) + | _ -> (invoke ob) meth args + +let _ = + let a = new_derived_object new_Foo (director_default_MyFoo) '(10) in + assert (a -> GetMsg () as string = "director_default_MyFoo-default"); + assert (a -> GetMsg ("boo") as string = "director_default_MyFoo-boo"); + let f = new_Foo '(10) in + assert (f -> GetMsg () as string = "Foo-default"); + assert (f -> GetMsg ("boo") as string = "Foo-boo"); + + let b = new_Bar '(1) in + assert (b -> GetMsg () as string = "Bar-default"); + assert (b -> GetMsg ("boo") as string = "Bar-boo"); + let b2 = new_Bar '() in + assert (b2 -> GetMsg () as string = "Bar-default"); + assert (b2 -> GetMsg ("boo") as string = "Bar-boo"); +;; diff --git a/Examples/test-suite/ocaml/director_exception_catches_runme.ml b/Examples/test-suite/ocaml/director_exception_catches_runme.ml new file mode 100644 index 000000000..322cdda45 --- /dev/null +++ b/Examples/test-suite/ocaml/director_exception_catches_runme.ml @@ -0,0 +1,15 @@ +open Swig +open Director_exception_catches + +exception CustomException of string + +let new_MyClass ob meth args = + match meth with + | "description" -> raise (CustomException "CustomException thrown in description().") + | _ -> (invoke ob) meth args + +let b = new_derived_object new_BaseClass (new_MyClass) '() +try + ignore (_BaseClass_call_description (b)); assert false +with CustomException s -> + assert (s = "CustomException thrown in description().") diff --git a/Examples/test-suite/ocaml/director_exception_nothrow_runme.ml b/Examples/test-suite/ocaml/director_exception_nothrow_runme.ml new file mode 100644 index 000000000..5b2b4b3d2 --- /dev/null +++ b/Examples/test-suite/ocaml/director_exception_nothrow_runme.ml @@ -0,0 +1,12 @@ +open Swig +open Director_exception_nothrow + +let _MyBar ob meth args = + match meth with + | "pang" -> C_string "_MyBar::pang()" + | _ -> (invoke ob) meth args + +let a = new_derived_object new_Bar (_MyBar) '() +let _ = assert (_MyBar a "pang" '() as string = "_MyBar::pang()") +let b = new_Bar '() +let _ = assert (b -> pang () as string = "Bar::pang()") diff --git a/Examples/test-suite/ocaml/director_exception_runme.ml b/Examples/test-suite/ocaml/director_exception_runme.ml new file mode 100644 index 000000000..1cd769b20 --- /dev/null +++ b/Examples/test-suite/ocaml/director_exception_runme.ml @@ -0,0 +1,46 @@ +open Swig +open Director_exception + +exception MyException of string * string + +let director_exception_MyFoo ob meth args = + match meth with + "ping" -> raise (Failure "MyFoo::ping() EXCEPTION") + | _ -> (invoke ob) meth args + +let director_exception_MyFoo2 ob meth args = + match meth with + "ping" -> (C_bool true) + | _ -> (invoke ob) meth args + +let director_exception_MyFoo3 ob meth args = + match meth with + "ping" -> raise (MyException ("foo", "bar")) + | _ -> (invoke ob) meth args + +(* Check that Failure is raised by MyFoo.ping() (via MyFoo.pong()). *) +let a = + new_derived_object + new_Foo (director_exception_MyFoo) '() +let a = _launder(a) +try + let _ = a -> pong () in assert false +with Failure s -> assert(s = "MyFoo::ping() EXCEPTION") + +let a = + new_derived_object + new_Foo (director_exception_MyFoo2) '() +let a = _launder(a) +try + let _ = a -> pong () in assert false +with Failure s -> assert(s = "No appropriate conversion found.") + +let a = + new_derived_object + new_Foo (director_exception_MyFoo3) '() +let a = _launder(a) +try + let _ = a -> pong () in assert false +with MyException (s1, s2) -> + assert (s1 = "foo"); + assert (s2 = "bar"); diff --git a/Examples/test-suite/ocaml/director_frob_runme.ml b/Examples/test-suite/ocaml/director_frob_runme.ml new file mode 100644 index 000000000..137a88ef3 --- /dev/null +++ b/Examples/test-suite/ocaml/director_frob_runme.ml @@ -0,0 +1,5 @@ +open Swig +open Director_frob + +let foo = new_Bravo '() +assert (foo -> abs_method () as string = "Bravo::abs_method()") diff --git a/Examples/test-suite/ocaml/director_ignore_runme.ml b/Examples/test-suite/ocaml/director_ignore_runme.ml new file mode 100644 index 000000000..b0d3b1451 --- /dev/null +++ b/Examples/test-suite/ocaml/director_ignore_runme.ml @@ -0,0 +1,18 @@ +open Swig +open Director_ignore + +let _DIgnoresDerived ob meth args = + match meth with + | "OverloadedMethod" -> C_int 0 + | _ -> (invoke ob) meth args + +let a =new_derived_object new_DIgnores (_DIgnoresDerived) '() +let _ = assert (a -> Triple (5) as int = 15) + +let _DAbstractIgnoresDerived ob meth args = + match meth with + | "OverloadedMethod" -> C_int 0 + | _ -> (invoke ob) meth args + +let a = new_derived_object new_DAbstractIgnores (_DAbstractIgnoresDerived) '() +let _ = assert (a -> Quadruple (5) as int = 20) diff --git a/Examples/test-suite/ocaml/director_pass_by_value_runme.ml b/Examples/test-suite/ocaml/director_pass_by_value_runme.ml new file mode 100644 index 000000000..af862f189 --- /dev/null +++ b/Examples/test-suite/ocaml/director_pass_by_value_runme.ml @@ -0,0 +1,24 @@ +open Swig +open Director_pass_by_value + +let passByVal = ref [| |] + +let director_pass_by_value_Derived ob meth args = + match meth with + | "virtualMethod" -> passByVal := Array.append !passByVal [|args|]; C_void + | _ -> (invoke ob) meth args + +let d = + new_derived_object + new_DirectorPassByValueAbstractBase + (director_pass_by_value_Derived) + '() + +let _ = + let caller = new_Caller '() in + assert (caller -> call_virtualMethod (d) = C_void); + assert (Array.length !passByVal = 1); + let a = List.hd (fnhelper (!passByVal.(0))) in + assert (a -> getVal () as int = 0x12345678); + assert (a -> "~" () = C_void); +;; diff --git a/Examples/test-suite/ocaml/director_unroll_runme.ml b/Examples/test-suite/ocaml/director_unroll_runme.ml new file mode 100644 index 000000000..747d9adf6 --- /dev/null +++ b/Examples/test-suite/ocaml/director_unroll_runme.ml @@ -0,0 +1,15 @@ +open Swig +open Director_unroll + +let director_unroll_MyFoo ob meth args = + match meth with + | "ping" -> C_string "MyFoo::ping()" + | _ -> (invoke ob) meth args + +let a = new_derived_object + new_Foo (director_unroll_MyFoo) '() + +let b = new_Bar '() +let _ = b -> set (a) +let c = b -> get () +let _ = assert ((a -> "&" () as int) = (c -> "&" () as int)) diff --git a/Examples/test-suite/ocaml/dynamic_cast_runme.ml b/Examples/test-suite/ocaml/dynamic_cast_runme.ml new file mode 100644 index 000000000..54391d9a0 --- /dev/null +++ b/Examples/test-suite/ocaml/dynamic_cast_runme.ml @@ -0,0 +1,9 @@ +open Swig +open Dynamic_cast + +let f = new_Foo '() +let b = new_Bar '() + +let x = f -> blah () +let y = b -> blah () +assert (_do_test '(y) as string = "Bar::test") diff --git a/Examples/test-suite/ocaml/exception_classname_runme.ml b/Examples/test-suite/ocaml/exception_classname_runme.ml new file mode 100644 index 000000000..8467ed6e8 --- /dev/null +++ b/Examples/test-suite/ocaml/exception_classname_runme.ml @@ -0,0 +1,5 @@ +open Swig +open Exception_classname + +let a = new_Exception '() +assert (a -> testfunc () as int = 42) diff --git a/Examples/test-suite/ocaml/exception_order_runme.ml b/Examples/test-suite/ocaml/exception_order_runme.ml new file mode 100644 index 000000000..9e987c84b --- /dev/null +++ b/Examples/test-suite/ocaml/exception_order_runme.ml @@ -0,0 +1,17 @@ +open Swig +open Exception_order + +let a = new_A '() + +let check meth args expected = + try + ignore ((invoke a) meth (args)); assert false + with Failure msg -> assert (msg = expected) + +let _ = + check "foo" '() "C++ E1 exception thrown"; + check "bar" '() "C++ E2 exception thrown"; + check "foobar" '() "postcatch unknown"; + check "barfoo" (C_int 1) "C++ E1 exception thrown"; + check "barfoo" (C_int 2) "C++ E2 * exception thrown"; +;; diff --git a/Examples/test-suite/ocaml/extend_constructor_destructor_runme.ml b/Examples/test-suite/ocaml/extend_constructor_destructor_runme.ml new file mode 100644 index 000000000..432d9d7dc --- /dev/null +++ b/Examples/test-suite/ocaml/extend_constructor_destructor_runme.ml @@ -0,0 +1,12 @@ +open Swig +open Extend_constructor_destructor + +let check o v = + assert ((o -> "[ivar]" () as int) = v); + ignore (o -> "~" ()); + assert ((_globalVar '() as int) = -v) + +let ctors = [new_AStruct; new_BStruct; new_CStruct; new_DStruct; new_EStruct; + new_FStruct; new_GStruct] + +let _ = List.iteri (fun i c -> let j = succ i in check (c (C_int j)) j) ctors diff --git a/Examples/test-suite/ocaml/extend_placement_runme.ml b/Examples/test-suite/ocaml/extend_placement_runme.ml new file mode 100644 index 000000000..31d9ae671 --- /dev/null +++ b/Examples/test-suite/ocaml/extend_placement_runme.ml @@ -0,0 +1,53 @@ +open Swig +open Extend_placement + +let _ = + let f = new_Foo '() in + assert (f -> spam () as int = 1); + assert (new_Foo '(1) -> spam () as int = 1); + let f = new_Foo '(1, 1) in + assert (f -> spam () as int = 1); + assert (f -> spam ("hello") as int = 2); + assert (f -> spam (1) as int = 1); + assert (f -> spam (1, 2) as int = 3); + assert (f -> spam (2, 4, 6) as int = 6); + assert (f -> spam (f) as int = 0); + let arg = C_double 1. in + assert (f -> spam (f, arg) as int = 0); + + assert (new_Bar '() -> spam () as int = 1); + let b = new_Bar '(1) in + assert (b -> spam () as int = 1); + assert (b -> spam ("hello") as int = 2); + assert (b -> spam (1) as int = 1); + assert (b -> spam (1, 2) as int = 3); + assert (b -> spam (2, 4, 6) as int = 6); + assert (b -> spam (b) as int = 0); + let arg = C_double 1. in + assert (b -> spam (b, arg) as int = 0); + + assert (new_FooTi '() -> spam () as int = 1); + assert (new_FooTi '(1) -> spam () as int = 1); + let f = new_FooTi '(1, 1) in + assert (f -> spam () as int = 1); + assert (f -> spam ("hello") as int = 2); + assert (f -> spam (1) as int = 1); + assert (f -> spam (1, 2) as int = 3); + assert (f -> spam (2, 4, 6) as int = 6); + let foo = new_Foo '() in + assert (f -> spam (foo) as int = 0); + let arg = C_double 1. in + assert (f -> spam (foo, arg) as int = 0); + + assert (new_BarTi '() -> spam () as int = 1); + let b = new_BarTi '(1) in + assert (b -> spam () as int = 1); + assert (b -> spam ("hello") as int = 2); + assert (b -> spam (1) as int = 1); + assert (b -> spam (1, 2) as int = 3); + assert (b -> spam (2, 4, 6) as int = 6); + let bar = new_Bar '() in + assert (b -> spam (bar) as int = 0); + let arg = C_double 1. in + assert (b -> spam (bar, arg) as int = 0); +;; diff --git a/Examples/test-suite/ocaml/extend_runme.ml b/Examples/test-suite/ocaml/extend_runme.ml new file mode 100644 index 000000000..695282f9c --- /dev/null +++ b/Examples/test-suite/ocaml/extend_runme.ml @@ -0,0 +1,26 @@ +open Swig +open Extend + +let _ = + let base1 = new_Base '() and base2 = new_Base '(10) in + assert ((base1 -> "[value]" () as int) = 0); + assert ((base2 -> "[value]" () as int) = 10); + let cint = C_int 5 in + assert ((base1 -> "method" (cint) as int) = 5); + assert ((_Base_zeroVal '() as int) = 0); + assert ((base2 -> "currentValue" () as int) = 10); + let cint = C_int 7 in + assert ((base2 -> "extendmethod" (cint) as int) = 14); +;; + +let _ = + let der1 = new_Derived '(0) and der2 = new_Derived '(17) in + assert ((der1 -> "[value]" () as int) = 0); + let cint = C_int 5 in + assert ((der1 -> "method" (cint) as int) = 10); + assert ((der2 -> "[value]" () as int) = 34); + let cfloat = C_float 200. in + ignore (der2 -> "[extendval]" (cfloat)); + assert (abs_float ((der2 -> "[actualval]" () as float) -. 2.) < 0.001); + assert (abs_float ((der2 -> "[extendval]" () as float) -. 200.) < 0.001); +;; diff --git a/Examples/test-suite/ocaml/extend_special_variables_runme.ml b/Examples/test-suite/ocaml/extend_special_variables_runme.ml new file mode 100644 index 000000000..387d8fd0a --- /dev/null +++ b/Examples/test-suite/ocaml/extend_special_variables_runme.ml @@ -0,0 +1,14 @@ +open Swig +open Extend_special_variables + +let f = new_ForExtensionNewName '() +let s = f -> "extended_renamed" () as string +let s2 = f -> "extended_renamed" (10) as string + +let _ = + assert (s = "name:extended symname:extended_renamed wrapname: overname:__SWIG_0 decl:ForExtension::extended() fulldecl:char const * ForExtension::extended() parentclasssymname:ForExtensionNewName parentclassname:ForExtension") + assert (s2 = "name:extended symname:extended_renamed wrapname: overname:__SWIG_1 decl:ForExtension::extended(int) fulldecl:char const * ForExtension::extended(int) parentclasssymname:ForExtensionNewName parentclassname:ForExtension") +;; + +let e = new_ExtendTemplateInt '() +let _ = e -> "extending" () diff --git a/Examples/test-suite/ocaml/extend_template_runme.ml b/Examples/test-suite/ocaml/extend_template_runme.ml new file mode 100644 index 000000000..2d611a14a --- /dev/null +++ b/Examples/test-suite/ocaml/extend_template_runme.ml @@ -0,0 +1,8 @@ +open Swig +open Extend_template + +let f = new_Foo_0 '() +let _ = + assert((f -> "test1" (37) as int) = 37); + assert((f -> "test2" (42) as int) = 42); +;; diff --git a/Examples/test-suite/ocaml/extend_typedef_class_runme.ml b/Examples/test-suite/ocaml/extend_typedef_class_runme.ml new file mode 100644 index 000000000..b5d97e2ad --- /dev/null +++ b/Examples/test-suite/ocaml/extend_typedef_class_runme.ml @@ -0,0 +1,12 @@ +open Swig +open Extend_typedef_class + +let test_obj o v = + let cint = C_int v in + let _ = o -> "[membervar]" (cint) in + assert ((o -> "getvar" () as int) = v) + +let ctors = [new_AClass; new_BClass; new_CClass; new_DClass; new_AStruct; + new_BStruct; new_CStruct; new_DStruct] + +let _ = List.iteri (fun i c -> test_obj (c '()) i) ctors diff --git a/Examples/test-suite/ocaml/extern_c_runme.ml b/Examples/test-suite/ocaml/extern_c_runme.ml new file mode 100644 index 000000000..18e672255 --- /dev/null +++ b/Examples/test-suite/ocaml/extern_c_runme.ml @@ -0,0 +1,4 @@ +open Swig +open Extern_c + +let _ = _RealFunction '(2) diff --git a/Examples/test-suite/ocaml/funcptr_cpp_runme.ml b/Examples/test-suite/ocaml/funcptr_cpp_runme.ml new file mode 100644 index 000000000..bdc077d4e --- /dev/null +++ b/Examples/test-suite/ocaml/funcptr_cpp_runme.ml @@ -0,0 +1,13 @@ +open Swig +open Funcptr_cpp + +let _ = + let fp = _ADD_BY_VALUE '() in + assert (_call1 '(fp, 10, 11) as int = 21); + let fp = _ADD_BY_POINTER '() in + assert (_call2 '(fp, 12, 13) as int = 25); + let fp = _ADD_BY_REFERENCE '() in + assert (_call3 '(fp, 14, 15) as int = 29); + let fp = _ADD_BY_VALUE_C '() in + assert (_call1 '(fp, 2, 3) as int = 5); +;; diff --git a/Examples/test-suite/ocaml/fvirtual_runme.ml b/Examples/test-suite/ocaml/fvirtual_runme.ml new file mode 100644 index 000000000..6b0782b20 --- /dev/null +++ b/Examples/test-suite/ocaml/fvirtual_runme.ml @@ -0,0 +1,10 @@ +open Swig +open Fvirtual + +let _ = + let sw = new_NodeSwitch '() and n = new_Node '() in + assert (n -> addChild (n) as int = 1); + assert (sw -> addChild (n) as int = 2); + assert (sw -> addChild (sw) as int = 2); + assert (sw -> addChild (n, false) as int = 3) +;; diff --git a/Examples/test-suite/ocaml/global_ns_arg_runme.ml b/Examples/test-suite/ocaml/global_ns_arg_runme.ml new file mode 100644 index 000000000..7717e52d9 --- /dev/null +++ b/Examples/test-suite/ocaml/global_ns_arg_runme.ml @@ -0,0 +1,5 @@ +open Swig +open Global_ns_arg + +let _ = assert ((_foo '(1) as int) = 1) +let _ = assert ((_bar_fn '() as int) = 1) diff --git a/Examples/test-suite/ocaml/global_vars_runme.ml b/Examples/test-suite/ocaml/global_vars_runme.ml new file mode 100644 index 000000000..75df89499 --- /dev/null +++ b/Examples/test-suite/ocaml/global_vars_runme.ml @@ -0,0 +1,15 @@ +open Swig +open Global_vars + +_init '() + +let _ = + assert (_b '() as string = "string b"); + assert (_b '("a string value") as string = "a string value"); + assert (_b '() as string = "a string value"); + assert (_x '() as int = 1234); + assert (_x '(9876) as int = 9876); + assert (_x '() as int = 9876); + assert (_Hi '() as int = 0); + assert (_Hola '() as int = 1); +;; diff --git a/Examples/test-suite/ocaml/ignore_parameter_runme.ml b/Examples/test-suite/ocaml/ignore_parameter_runme.ml new file mode 100644 index 000000000..358b25ebb --- /dev/null +++ b/Examples/test-suite/ocaml/ignore_parameter_runme.ml @@ -0,0 +1,20 @@ +open Swig +open Ignore_parameter + +let _ = + assert (get_string (_jaguar (C_list [ C_int 200 ; C_float 0. ])) = "hello"); + assert (get_int (_lotus (C_list [ C_string "fast" ; C_float 0. ])) = 101); + assert (get_float (_tvr (C_list [ C_string "fast" ; C_int 200 ])) = 8.8); + assert (get_int (_ferrari (C_void)) = 101); +;; +let sc = new_SportsCars (C_void) +let _ = + assert (get_string ((invoke sc) "daimler" (C_list [ C_int 200 ; C_float 0. ])) = "hello"); + assert (get_int ((invoke sc) "astonmartin" (C_list [ C_string "fast" ; C_float 0. ])) = 101); + assert (get_float ((invoke sc) "bugatti" (C_list [ C_string "fast" ; C_int 200 ])) = 8.8); + assert (get_int ((invoke sc) "lamborghini" (C_void)) = 101); +;; +let mc = new_MiniCooper (C_list [ C_int 200 ; C_float 0. ]) +let mm = new_MorrisMinor (C_list [ C_string "slow" ; C_float 0. ]) +let fa = new_FordAnglia (C_list [ C_string "slow" ; C_int 200 ]) +let aa = new_AustinAllegro (C_void) diff --git a/Examples/test-suite/ocaml/inctest_runme.ml b/Examples/test-suite/ocaml/inctest_runme.ml new file mode 100644 index 000000000..886751109 --- /dev/null +++ b/Examples/test-suite/ocaml/inctest_runme.ml @@ -0,0 +1,7 @@ +open Swig +open Inctest + +let _ = new_A '() +let _ = new_B '() +let _ = assert (_importtest1 '(5) as int = 15) +let _ = assert (_importtest2 '("black") as string = "white") diff --git a/Examples/test-suite/ocaml/inherit_missing_runme.ml b/Examples/test-suite/ocaml/inherit_missing_runme.ml new file mode 100644 index 000000000..3d1901356 --- /dev/null +++ b/Examples/test-suite/ocaml/inherit_missing_runme.ml @@ -0,0 +1,10 @@ +open Swig +open Inherit_missing + +let _ = + let a = _new_Foo '() and b = new_Bar '() and c = new_Spam '() in + assert (_do_blah '(a) as string = "Foo::blah"); + assert (_do_blah '(b) as string = "Bar::blah"); + assert (_do_blah '(c) as string = "Spam::blah"); + assert (_delete_Foo '(a) = C_void) +;; diff --git a/Examples/test-suite/ocaml/inout_runme.ml b/Examples/test-suite/ocaml/inout_runme.ml new file mode 100644 index 000000000..767bb43e6 --- /dev/null +++ b/Examples/test-suite/ocaml/inout_runme.ml @@ -0,0 +1,8 @@ +open Swig +open Inout + +let _ = + assert (_AddOne1 '(1.) as float = 2.); + assert (_AddOne3 '(1, 1, 1) = C_list ['2.;'2.;'2.]); + assert (_AddOne1r '(1.) as float = 2.); +;; diff --git a/Examples/test-suite/ocaml/li_cpointer_cpp_runme.ml b/Examples/test-suite/ocaml/li_cpointer_cpp_runme.ml new file mode 100644 index 000000000..1daf6b5bd --- /dev/null +++ b/Examples/test-suite/ocaml/li_cpointer_cpp_runme.ml @@ -0,0 +1,10 @@ +open Swig +open Li_cpointer_cpp + +let _ = + let p = _new_intp '() in + assert (_intp_value '(p) as int = 0); + assert (_intp_assign '(p, 3) = C_void); + assert (_intp_value '(p) as int = 3); + assert (_delete_intp '(p) = C_void) +;; diff --git a/Examples/test-suite/ocaml/li_std_except_runme.ml b/Examples/test-suite/ocaml/li_std_except_runme.ml new file mode 100644 index 000000000..e6ad14dc3 --- /dev/null +++ b/Examples/test-suite/ocaml/li_std_except_runme.ml @@ -0,0 +1,18 @@ +open Swig +open Li_std_except + +let _ = + let t = new_Test '() in + try let _ = t -> throw_bad_cast () in assert false with Failure s -> (); + try let _ = t -> throw_bad_exception () in assert false with Failure s -> (); + try let _ = t -> throw_domain_error () in assert false with Failure s -> assert (s = "oops"); + try let _ = t -> throw_exception () in assert false with Failure s -> (); + try let _ = t -> throw_invalid_argument () in assert false with Invalid_argument s -> assert (s = "oops"); + try let _ = t -> throw_length_error () in assert false with Failure s -> assert (s = "oops"); + try let _ = t -> throw_logic_error () in assert false with Failure s -> assert (s = "oops"); + try let _ = t -> throw_out_of_range () in assert false with Failure s -> assert (s = "oops"); + try let _ = t -> throw_overflow_error () in assert false with Failure s -> assert (s = "oops"); + try let _ = t -> throw_range_error () in assert false with Failure s -> assert (s = "oops"); + try let _ = t -> throw_runtime_error () in assert false with Failure s -> assert (s = "oops"); + try let _ = t -> throw_underflow_error () in assert false with Failure s -> assert (s = "oops"); +;; diff --git a/Examples/test-suite/ocaml/li_std_vector_runme.ml b/Examples/test-suite/ocaml/li_std_vector_runme.ml new file mode 100644 index 000000000..64e9ec9f2 --- /dev/null +++ b/Examples/test-suite/ocaml/li_std_vector_runme.ml @@ -0,0 +1,23 @@ +open Swig +open Li_std_vector + +let _ = + let iv = new_IntVector '() in + assert (iv -> "empty" () as bool); + assert ((iv -> "size" () as int) = 0); + ignore (iv -> "push_back" (123)); + assert ((iv -> "empty" () as bool) = false); + assert ((iv -> "size" () as int) = 1); + assert ((iv -> "[]" (0) as int) = 123); + ignore (iv -> "clear" ()); + assert (iv -> "empty" () as bool); + assert ((iv -> "size" () as int) = 0); +;; + +let _ = + let rv = new_RealVector '() in + ignore (rv -> "push_back" (100.)); + ignore (rv -> "push_back" (200.)); + assert ((rv -> "[]" (0) as float) = 100.); + assert ((rv -> "[]" (1) as float) = 200.); +;; diff --git a/Examples/test-suite/ocaml/memberin_extend_runme.ml b/Examples/test-suite/ocaml/memberin_extend_runme.ml new file mode 100644 index 000000000..e2cca2275 --- /dev/null +++ b/Examples/test-suite/ocaml/memberin_extend_runme.ml @@ -0,0 +1,10 @@ +open Swig +open Memberin_extend + +let _ = + let em1 = new_ExtendMe '() and em2 = new_ExtendMe '() in + assert (em1 -> "[thing]" ("em1thing") = C_void); + assert (em2 -> "[thing]" ("em2thing") = C_void); + assert (em1 -> "[thing]" () as string = "em1thing"); + assert (em2 -> "[thing]" () as string = "em2thing"); +;; diff --git a/Examples/test-suite/ocaml/multivalue_runme.ml b/Examples/test-suite/ocaml/multivalue_runme.ml new file mode 100644 index 000000000..d7e19e7d8 --- /dev/null +++ b/Examples/test-suite/ocaml/multivalue_runme.ml @@ -0,0 +1,8 @@ +open Swig +open Multivalue + +let _ = + assert (_divide_l '(37, 5) = C_list ['7;'2]); + assert (_divide_v '(41, 7) = C_list ['5;'6]); + assert (_divide_mv '(91, 13) = C_list ['7;'0]); +;; diff --git a/Examples/test-suite/ocaml/namespace_virtual_method_runme.ml b/Examples/test-suite/ocaml/namespace_virtual_method_runme.ml new file mode 100644 index 000000000..3c5b2cf34 --- /dev/null +++ b/Examples/test-suite/ocaml/namespace_virtual_method_runme.ml @@ -0,0 +1,4 @@ +open Swig +open Namespace_virtual_method + +let x = new_Spam '() diff --git a/Examples/test-suite/ocaml/newobject2_runme.ml b/Examples/test-suite/ocaml/newobject2_runme.ml new file mode 100644 index 000000000..eb9a191bc --- /dev/null +++ b/Examples/test-suite/ocaml/newobject2_runme.ml @@ -0,0 +1,16 @@ +open Swig +open Newobject2 + +let _ = + assert (_fooCount '() as int = 0); + let foo1 = _makeFoo '() in + assert (_fooCount '() as int = 1); + assert (_do_stuff '(foo1) = C_void); + let foo2 = _makeFoo '() in + assert (_fooCount '() as int = 2); + assert (_do_stuff '(foo2) = C_void); + ignore (foo1 -> "~" ()); + assert (_fooCount '() as int = 1); + ignore (foo2 -> "~" ()); + assert (_fooCount '() as int = 0) +;; diff --git a/Examples/test-suite/ocaml/overload_bool_runme.ml b/Examples/test-suite/ocaml/overload_bool_runme.ml new file mode 100644 index 000000000..fefd07429 --- /dev/null +++ b/Examples/test-suite/ocaml/overload_bool_runme.ml @@ -0,0 +1,26 @@ +open Swig +open Overload_bool + +let _ = + assert (_overloaded '(true) as string = "bool"); + assert (_overloaded '(false) as string = "bool"); + assert (_overloaded '(0) as string = "int"); + assert (_overloaded '(1) as string = "int"); + assert (_overloaded '(2) as string = "int"); + assert (_overloaded '("1234") as string = "string"); + assert (_boolfunction '(true) as string = "true"); + assert (_boolfunction '(false) as string = "false"); + assert (_intfunction '(true) as string = "int"); + assert (_intfunction '(false) as string = "int"); + + assert (_overloaded_ref '(true) as string = "bool"); + assert (_overloaded_ref '(false) as string = "bool"); + assert (_overloaded_ref '(0) as string = "int"); + assert (_overloaded_ref '(1) as string = "int"); + assert (_overloaded_ref '(2) as string = "int"); + assert (_overloaded_ref '("1234") as string = "string"); + assert (_boolfunction_ref '(true) as string = "true"); + assert (_boolfunction_ref '(false) as string = "false"); + assert (_intfunction_ref '(true) as string = "int"); + assert (_intfunction_ref '(false) as string = "int"); +;; diff --git a/Examples/test-suite/ocaml/overload_extend_runme.ml b/Examples/test-suite/ocaml/overload_extend_runme.ml new file mode 100644 index 000000000..3793cdbb0 --- /dev/null +++ b/Examples/test-suite/ocaml/overload_extend_runme.ml @@ -0,0 +1,11 @@ +open Swig +open Overload_extend + +let _ = + let f = new_Foo '() in + assert (f -> test () as int = 0); + assert (f -> test (3) as int = 1); + assert (f -> test ("hello") as int = 2); + assert (f -> test (3., 2.) as float = 5.); + assert (f -> test (3.) as float = 1003.) +;; diff --git a/Examples/test-suite/ocaml/overload_method_runme.ml b/Examples/test-suite/ocaml/overload_method_runme.ml new file mode 100644 index 000000000..0303ba2a3 --- /dev/null +++ b/Examples/test-suite/ocaml/overload_method_runme.ml @@ -0,0 +1,11 @@ +open Swig +open Overload_method + +let _ = + let b = new_Base '() in + assert (b -> "method" () as int = 42); + assert (b -> "overloaded_method" () as int = 42); + assert (b -> "overloaded_method" (5) = C_void); + assert (b -> "overloaded_method" () as int = 5); + assert (b -> "method" () as int = 5); +;; diff --git a/Examples/test-suite/ocaml/overload_numeric_runme.ml b/Examples/test-suite/ocaml/overload_numeric_runme.ml new file mode 100644 index 000000000..0342d63e0 --- /dev/null +++ b/Examples/test-suite/ocaml/overload_numeric_runme.ml @@ -0,0 +1,14 @@ +open Swig +open Overload_numeric + +let _ = + let n = new_Nums '() in + let arg = C_char 'c' in + assert (n -> over (arg) as string = "signed char"); + let arg = C_short 2 in + assert (n -> over (arg) as string = "short"); + assert (n -> over (2) as string = "int"); + let arg = C_float 2. in + assert (n -> over (arg) as string = "float"); + assert (n -> over (2.) as string = "double") +;; diff --git a/Examples/test-suite/ocaml/overload_polymorphic_runme.ml b/Examples/test-suite/ocaml/overload_polymorphic_runme.ml new file mode 100644 index 000000000..5ed5f45f4 --- /dev/null +++ b/Examples/test-suite/ocaml/overload_polymorphic_runme.ml @@ -0,0 +1,9 @@ +open Swig +open Overload_polymorphic + +let _ = + let t = new_Derived '() in + assert (_test (t) as int = 0); + assert (_test '(1) as int = 1); + assert (_test2 (t) as int = 1) +;; diff --git a/Examples/test-suite/ocaml/overload_rename_runme.ml b/Examples/test-suite/ocaml/overload_rename_runme.ml new file mode 100644 index 000000000..9e012c0c5 --- /dev/null +++ b/Examples/test-suite/ocaml/overload_rename_runme.ml @@ -0,0 +1,7 @@ +open Swig +open Overload_rename + +let _ = new_Foo (C_float 1.) +let _ = new_Foo (C_list [ C_float 1. ; C_float 1. ]) +let _ = new_Foo_int (C_list [ C_float 1. ; C_int 1 ]) +let _ = new_Foo_int (C_list [ C_float 1. ; C_int 1 ; C_float 1. ]) diff --git a/Examples/test-suite/ocaml/overload_subtype_runme.ml b/Examples/test-suite/ocaml/overload_subtype_runme.ml new file mode 100644 index 000000000..6f0aeab56 --- /dev/null +++ b/Examples/test-suite/ocaml/overload_subtype_runme.ml @@ -0,0 +1,8 @@ +open Swig +open Overload_subtype + +let _ = + let f = new_Foo '() and b = new_Bar '() in + assert (_spam (f) as int = 1); + assert (_spam (b) as int = 2) +;; diff --git a/Examples/test-suite/ocaml/overload_template_runme.ml b/Examples/test-suite/ocaml/overload_template_runme.ml new file mode 100644 index 000000000..42a4a397a --- /dev/null +++ b/Examples/test-suite/ocaml/overload_template_runme.ml @@ -0,0 +1,60 @@ +open Swig +open Overload_template + +let _ = + assert (_foo '() as int = 3); + assert (_maximum '(3, 4) as int = 4); + assert (_maximum '(3.4, 5.2) as float > 5.); + assert (_mix1 '("hi") as int = 101); + assert (_mix1 '(1.0, 1.0) as int = 102); + assert (_mix1 '(1.0) as int = 103); + assert (_mix2 '("hi") as int = 101); + assert (_mix2 '(1.0, 1.0) as int = 102); + assert (_mix2 '(1.0) as int = 103); + assert (_mix3 '("hi") as int = 101); + assert (_mix3 '(1.0, 1.0) as int = 102); + assert (_mix3 '(1.0) as int = 103); + + assert (_overtparams1 '(100) as int = 10); + assert (_overtparams1 '(100.0, 100) as int = 20); + assert (_overtparams2 '(100.0, 100) as int = 40); + assert (_overloaded '() as int = 60); + assert (_overloaded '(100.0, 100) as int = 70); + assert (_overloadedagain '("hello") as int = 80); + assert (_overloadedagain '() as int = 90); + + assert (_specialization '(10) as int = 202); + assert (_specialization '(10.0) as int = 203); + assert (_specialization '(10, 10) as int = 204); + assert (_specialization '(10.0, 10.0) as int = 205); + assert (_specialization '("hi", "hi") as int = 201); + + assert (_xyz '() = C_void); + assert (_xyz_int '() = C_void); + assert (_xyz_double '() = C_void); + + assert (_overload '("hi") as int = 0); + assert (_overload '(1) as int = 10); + assert (_overload '(1, 1) as int = 20); + assert (_overload '(1, "hello") as int = 30); + let k = new_Klass '() in + assert (_overload '(k) as int = 10); + assert (_overload '(k, k) as int = 20); + assert (_overload '(k, "hello") as int = 30); + assert (_overload '(10.0, "hi") as int = 40); + assert (_overload '() as int = 50); + + assert (_nsoverload '("hi") as int = 1000); + assert (_nsoverload '(1) as int = 1010); + assert (_nsoverload '(1, 1) as int = 1020); + assert (_nsoverload '(1, "hello") as int = 1030); + assert (_nsoverload '(k) as int = 1010); + assert (_nsoverload '(k, k) as int = 1020); + assert (_nsoverload '(k, "hello") as int = 1030); + assert (_nsoverload '(10.0, "hi") as int = 1040); + assert (_nsoverload '() as int = 1050); + + assert (_A_foo '(1) = C_void); + let b = new_B '() in + assert (b -> foo(1) = C_void); +;; diff --git a/Examples/test-suite/ocaml/primitive_ref_runme.ml b/Examples/test-suite/ocaml/primitive_ref_runme.ml new file mode 100644 index 000000000..7c96caac2 --- /dev/null +++ b/Examples/test-suite/ocaml/primitive_ref_runme.ml @@ -0,0 +1,20 @@ +open Swig +open Primitive_ref + +let _ = + assert (_ref_int '(3) as int = 3); + assert (_ref_short '(3) as int = 3); + assert (_ref_ushort '(3) as int = 3); + assert (_ref_long '(3) as int = 3); + assert (_ref_ulong '(3) as int = 3); + assert (_ref_schar '(3) as int = 3); + assert (_ref_uchar '(3) as int = 3); + assert (_ref_float '(3.5) as float = 3.5); + assert (_ref_double '(3.5) as float = 3.5); + assert (_ref_bool '(true) as bool = true); + let arg = C_char 'x' in + assert (_ref_char '(arg) as char = 'x'); + assert (_ref_over '(0) as int = 0); + let a = new_A '(12) in + assert (_ref_over '(a) as int = 12); +;; diff --git a/Examples/test-suite/ocaml/reference_global_vars_runme.ml b/Examples/test-suite/ocaml/reference_global_vars_runme.ml new file mode 100644 index 000000000..adde1b82e --- /dev/null +++ b/Examples/test-suite/ocaml/reference_global_vars_runme.ml @@ -0,0 +1,57 @@ +open Swig +open Reference_global_vars + +let _ = + let tc = _getconstTC '() in + assert (tc -> "[num]" () as int = 33); + + let _ = _var_bool (_createref_bool (C_bool false)) in + assert (_value_bool (_var_bool '()) as bool = false); + + let _ = _var_bool (_createref_bool (C_bool true)) in + assert (_value_bool (_var_bool '()) as bool = true); + + let _ = _var_char (_createref_char (C_char 'w')) in + assert (_value_char (_var_char '()) as char = 'w'); + + let _ = _var_unsigned_char (_createref_unsigned_char (C_uchar 'w')) in + assert (_value_unsigned_char (_var_unsigned_char '()) as char = 'w'); + + let _ = _var_signed_char (_createref_signed_char (C_uchar 'w')) in + assert (_value_signed_char (_var_signed_char '()) as char = 'w'); + + let _ = _var_short (_createref_short (C_short 10)) in + assert (_value_short (_var_short '()) as int = 10); + + let _ = _var_unsigned_short (_createref_unsigned_short (C_ushort 10)) in + assert (_value_unsigned_short (_var_unsigned_short '()) as int = 10); + + let _ = _var_int (_createref_int (C_int 10)) in + assert (_value_int (_var_int '()) as int = 10); + + let _ = _var_unsigned_int (_createref_unsigned_int (C_int 10)) in + assert (_value_unsigned_int (_var_unsigned_int '()) as int = 10); + + let _ = _var_long (_createref_long (C_int64 10L)) in + assert (_value_long (_var_long '()) as int = 10); + + let _ = _var_unsigned_long (_createref_unsigned_long (C_int64 10L)) in + assert (_value_unsigned_long (_var_unsigned_long '()) as int = 10); + + let _ = _var_long_long (_createref_long_long (C_int64 0x6FFFFFFFFFFFFFF8L)) in + assert (_value_long_long (_var_long_long '()) = C_int64 0x6FFFFFFFFFFFFFF8L); + + let _ = _var_unsigned_long_long (_createref_unsigned_long_long (C_int64 0x6FFFFFFFFFFFFFF8L)) in + assert (_value_unsigned_long_long (_var_unsigned_long_long '()) = C_int64 0x6FFFFFFFFFFFFFF8L); + + let _ = _var_float (_createref_float (C_float 10.)) in + assert (_value_float (_var_float '()) as float = 10.); + + let _ = _var_double (_createref_double (C_double 10.)) in + assert (_value_double (_var_double '()) as float = 10.); + + let tc = new_TestClass '(20) in + let _ = _var_TestClass (_createref_TestClass (tc)) in + let tc = _value_TestClass (_var_TestClass '()) in + assert (tc -> "[num]" () as int = 20); +;; diff --git a/Examples/test-suite/ocaml/rename_predicates_runme.ml b/Examples/test-suite/ocaml/rename_predicates_runme.ml new file mode 100644 index 000000000..984600207 --- /dev/null +++ b/Examples/test-suite/ocaml/rename_predicates_runme.ml @@ -0,0 +1,40 @@ +open Swig +open Rename_predicates + +let _ = + let r = new_RenamePredicates '(123) in + assert (r -> MF_member_function () = C_void); + assert (_RenamePredicates_MF_static_member_function '() = C_void); + assert (r -> MF_member_function () = C_void); + assert (r -> MF_extend_function_before () = C_void); + assert (r -> MF_extend_function_after () = C_void); + assert (_GF_global_function '() = C_void); + + assert (r -> "[MV_member_variable]" () as int = 123); + assert (r -> "[MV_member_variable]" (1234) = C_void); + assert (r -> "[MV_member_variable]" () as int = 1234); + + assert (_RenamePredicates_MV_static_member_variable '() as int = 456); + assert (_RenamePredicates_MV_static_member_variable '(4567) as int = 4567); + assert (_RenamePredicates_MV_static_member_variable '() as int = 4567); + + assert (_GV_global_variable '() as int = 789); + assert (_GV_global_variable '(7890) as int = 7890); + assert (_GV_global_variable '() as int = 7890); + + assert (_UC_UPPERCASE '() = C_void); + assert (_LC_lowercase '() = C_void); + assert (_TI_Title '() = C_void); + assert (_FU_FirstUpperCase '() = C_void); + assert (_FL_firstLowerCase '() = C_void); + assert (_CA_CamelCase '() = C_void); + assert (_LC_lowerCamelCase '() = C_void); + assert (_UC_under_case_it '() = C_void); + + let ex = new_ExtendCheck '() in + assert (ex -> MF_real_member1 () = C_void); + assert (ex -> MF_real_member2 () = C_void); + assert (ex -> EX_EXTENDMETHOD1 () = C_void); + assert (ex -> EX_EXTENDMETHOD2 () = C_void); + assert (ex -> EX_EXTENDMETHOD3 () = C_void) +;; diff --git a/Examples/test-suite/ocaml/sizet_runme.ml b/Examples/test-suite/ocaml/sizet_runme.ml new file mode 100644 index 000000000..5f72459c9 --- /dev/null +++ b/Examples/test-suite/ocaml/sizet_runme.ml @@ -0,0 +1,10 @@ +open Swig +open Sizet + +let _ = + let s = C_int64 2000L in + assert (_test1 '(s) as int = 2000); + assert (_test2 '(s) as int = 2000); + assert (_test3 '(s) as int = 2000); + assert (_test4 '(s) as int = 2000); +;; diff --git a/Examples/test-suite/ocaml/special_variable_macros_runme.ml b/Examples/test-suite/ocaml/special_variable_macros_runme.ml new file mode 100644 index 000000000..7f4980ea3 --- /dev/null +++ b/Examples/test-suite/ocaml/special_variable_macros_runme.ml @@ -0,0 +1,14 @@ +open Swig +open Special_variable_macros + +let _ = + let name = new_Name '() in + assert (_testFred '(name) as string = "none"); + assert (_testJack '(name) as string = "$specialname"); + assert (_testJill '(name) as string = "jilly"); + assert (_testMary '(name) as string = "SWIGTYPE_p_NameWrap"); + assert (_testJames '(name) as string = "SWIGTYPE_Name"); + assert (_testJim '(name) as string = "multiname num"); + let arg = new_PairIntBool '(10, false) in + assert (_testJohn '(arg) as int = 123); +;; diff --git a/Examples/test-suite/ocaml/special_variables_runme.ml b/Examples/test-suite/ocaml/special_variables_runme.ml new file mode 100644 index 000000000..b569a54be --- /dev/null +++ b/Examples/test-suite/ocaml/special_variables_runme.ml @@ -0,0 +1,36 @@ +open Swig +open Special_variables + +let _ = + assert (_ExceptionVars '(1.0, 2.0) as string = + "result = Space::exceptionvars(arg1,arg2); Space::exceptionvars ExceptionVars _wrap_ExceptionVarsspecial_variables "); + assert (_overloadedmethod '() as string = + "result = Space::overloadedmethod(); Space::overloadedmethod overloadedmethod __SWIG_1 _wrap_overloadedmethod__SWIG_1special_variables "); + assert (_overloadedmethod '(10.0) as string = + "result = Space::overloadedmethod(arg1); Space::overloadedmethod overloadedmethod __SWIG_0 _wrap_overloadedmethod__SWIG_0special_variables "); + + let _ = new_ABC '(0, 0.0) in + assert (_declaration '() as string = "SpaceNamespace::ABC::ABC(int,double) SpaceNamespace::ABC::ABC(int,double)"); + let a = new_ABC '() in + assert (_declaration '() as string = "SpaceNamespace::ABC::ABC() SpaceNamespace::ABC::ABC()"); + ignore (a -> instancemethod (1)); + assert (_declaration '() as string = "short * SpaceNamespace::ABC::instancemethod(int) SpaceNamespace::ABC::instancemethod(int)"); + ignore (a -> instancemethod (1, false)); + assert (_declaration '() as string = "short * SpaceNamespace::ABC::instancemethod(int,bool) SpaceNamespace::ABC::instancemethod(int,bool)"); + ignore (a -> constmethod (1)); + assert (_declaration '() as string = "short * SpaceNamespace::ABC::constmethod(int) const SpaceNamespace::ABC::constmethod(int) const"); + ignore (_ABC_staticmethod '(0, false)); + assert (_declaration '() as string = "short * SpaceNamespace::ABC::staticmethod(int,bool) SpaceNamespace::ABC::staticmethod(int,bool)"); + ignore (a -> "~" ()); + assert (_declaration '() as string = "SpaceNamespace::ABC::~ABC() SpaceNamespace::ABC::~ABC()"); + let abc = new_TemplateABC '() in + assert (_declaration '() as string = "SpaceNamespace::Template< SpaceNamespace::ABC >::Template() SpaceNamespace::Template< SpaceNamespace::ABC >::Template()"); + let arg = new_ABC '() in + ignore (abc -> tmethod (arg)); + assert (_declaration '() as string = "std::string SpaceNamespace::Template< SpaceNamespace::ABC >::tmethod(SpaceNamespace::ABC) SpaceNamespace::Template< SpaceNamespace::ABC >::tmethod(SpaceNamespace::ABC)"); + ignore (abc -> "~" ()); + assert (_declaration '() as string = "SpaceNamespace::Template< SpaceNamespace::ABC >::~Template() SpaceNamespace::Template< SpaceNamespace::ABC >::~Template()"); + let arg = new_TemplateABC '() in + ignore (_globtemplate (arg)); + assert (_declaration '() as string = "void SpaceNamespace::globtemplate(SpaceNamespace::Template< SpaceNamespace::ABC >) SpaceNamespace::globtemplate(SpaceNamespace::Template< SpaceNamespace::ABC >)"); +;; diff --git a/Examples/test-suite/ocaml/static_const_member_runme.ml b/Examples/test-suite/ocaml/static_const_member_runme.ml new file mode 100644 index 000000000..02dd2fe4b --- /dev/null +++ b/Examples/test-suite/ocaml/static_const_member_runme.ml @@ -0,0 +1,9 @@ +open Swig +open Static_const_member + +let _ = + assert (_X_PN '() as int = 0); + assert (_X_CN '() as int = 1); + assert (_X_EN '() as int = 2); + assert (_X_CHARTEST '() as char = 'A'); +;; diff --git a/Examples/test-suite/ocaml/string_simple_runme.ml b/Examples/test-suite/ocaml/string_simple_runme.ml new file mode 100644 index 000000000..327fb85d2 --- /dev/null +++ b/Examples/test-suite/ocaml/string_simple_runme.ml @@ -0,0 +1,9 @@ +open Swig +open String_simple + +let str = "olĂ©" + +let copy = _copy_str (C_string str) as string + +let _ = if str <> copy then + raise (Failure ("Error: copy is not equal: original="^str^", copy="^copy)) diff --git a/Examples/test-suite/ocaml/struct_value_runme.ml b/Examples/test-suite/ocaml/struct_value_runme.ml new file mode 100644 index 000000000..73688bef3 --- /dev/null +++ b/Examples/test-suite/ocaml/struct_value_runme.ml @@ -0,0 +1,11 @@ +open Swig +open Struct_value + +let b = new_Bar (C_void) +let a = (invoke b) "[a]" (C_void) +let _ = (invoke a) "[x]" (C_int 3) +let _ = assert((invoke a) "[x]" (C_void) = C_int 3) + +let bb = (invoke b) "[b]" (C_void) +let _ = (invoke bb) "[x]" (C_int 3) +let _ = assert((invoke bb) "[x]" (C_void) = C_int 3) diff --git a/Examples/test-suite/ocaml/swig_exception_runme.ml b/Examples/test-suite/ocaml/swig_exception_runme.ml new file mode 100644 index 000000000..5bf36c36f --- /dev/null +++ b/Examples/test-suite/ocaml/swig_exception_runme.ml @@ -0,0 +1,13 @@ +open Swig +open Swig_exception + +let _ = + let c = new_Circle '(10) and s = new_Square '(10) in + assert (_Shape_nshapes '() as int = 2); + try + ignore (c -> throwException ()); assert false + with Sys_error msg -> assert (msg = "OK"); + let _ = c -> "~" () in + let _ = s -> "~" () in + assert (_Shape_nshapes '() as int = 0); +;; diff --git a/Examples/test-suite/ocaml/template_default_arg_overloaded_extend_runme.ml b/Examples/test-suite/ocaml/template_default_arg_overloaded_extend_runme.ml new file mode 100644 index 000000000..27fb9b543 --- /dev/null +++ b/Examples/test-suite/ocaml/template_default_arg_overloaded_extend_runme.ml @@ -0,0 +1,17 @@ +open Swig +open Template_default_arg_overloaded_extend + +let _ = + let rs = new_ResultSet '() and sp = new_SearchPoint '() in + assert (rs -> go_get_method (0, sp) as int = -1); + assert (rs -> go_get_method (0, sp, 100) as int = 100); + assert (rs -> go_get_template (0, sp) as int = -2); + assert (rs -> go_get_template (0, sp, 100) as int = 100); + + assert (rs -> over () as string = "over(int)"); + assert (rs -> over (10) as string = "over(int)"); + assert (rs -> over (sp) as string = "over(giai2::SearchPoint, int)"); + assert (rs -> over (sp, 10) as string = "over(giai2::SearchPoint, int)"); + assert (rs -> over (true, sp) as string = "over(bool, gaia2::SearchPoint, int)"); + assert (rs -> over (true, sp, 10) as string = "over(bool, gaia2::SearchPoint, int)"); +;; diff --git a/Examples/test-suite/ocaml/template_default_arg_runme.ml b/Examples/test-suite/ocaml/template_default_arg_runme.ml new file mode 100644 index 000000000..94f2291f1 --- /dev/null +++ b/Examples/test-suite/ocaml/template_default_arg_runme.ml @@ -0,0 +1,52 @@ +open Swig +open Template_default_arg + +let _ = + let helloInt = new_Hello_int '() and enumArg = _hi '() in + assert (helloInt -> foo (enumArg) = C_void); + assert (helloInt -> foo () = C_void); + + let x = new_X_int '() in + assert (x -> meth (20.0, 200) as int = 200); + assert (x -> meth (20) as int = 20); + assert (x -> meth () as int = 0); + + let x = new_Y_unsigned '() in + let args = C_list [ C_double 20.0 ; C_uint 200l ] in + assert (x -> meth (args) as int = 200); + let args = C_uint 20l in + assert (x -> meth (args) as int = 20); + assert (x -> meth () as int = 0); + + let x = new_X_longlong '() in + assert (x -> meth (20.0) as int = 0); + let x = new_X_longlong '(20.0) in + assert (x -> meth (20.0) as int = 0); + let args = C_list [ C_double 20.0 ; C_int64 200L ] in + let x = new_X_longlong '(args) in + assert (x -> meth (20.0) as int = 0); + + let x = new_X_int '() in + assert (x -> meth (20.0) as int = 0); + let x = new_X_int '(20.0) in + assert (x -> meth (20.0) as int = 0); + let x = new_X_int '(20.0, 200) in + assert (x -> meth (20.0) as int = 0); + + let arg = new_Foo_int '() in + assert (_ott '(arg) as int = 30); + assert (_ott '() as int = 10); + assert (_ott '(1) as int = 10); + assert (_ott '(1, 1) as int = 10); + assert (_ott '("hi") as int = 20); + assert (_ott '("hi", 1) as int = 20); + assert (_ott '("hi", 1, 1) as int = 20); + + let arg = new_Hello_int '() in + assert (_ottstring '(arg, "hi") as int = 40); + assert (_ottstring '(arg) as int = 40); + assert (_ottint '(arg, 1) as int = 50); + assert (_ottint '(arg) as int = 50); + assert (_ott '(arg, 1.0) as int = 60); + assert (_ott '(arg) as int = 60); +;; diff --git a/Examples/test-suite/ocaml/template_extend1_runme.ml b/Examples/test-suite/ocaml/template_extend1_runme.ml new file mode 100644 index 000000000..b9b5a67d6 --- /dev/null +++ b/Examples/test-suite/ocaml/template_extend1_runme.ml @@ -0,0 +1,8 @@ +open Swig +open Template_extend1 + +let _ = + let a = new_lBaz '() and b = new_dBaz '() in + assert (a -> foo () as string = "lBaz::foo"); + assert (b -> foo () as string = "dBaz::foo") +;; diff --git a/Examples/test-suite/ocaml/template_extend2_runme.ml b/Examples/test-suite/ocaml/template_extend2_runme.ml new file mode 100644 index 000000000..67f260f87 --- /dev/null +++ b/Examples/test-suite/ocaml/template_extend2_runme.ml @@ -0,0 +1,8 @@ +open Swig +open Template_extend2 + +let _ = + let a = new_lBaz '() and b = new_dBaz '() in + assert (a -> foo () as string = "lBaz::foo"); + assert (b -> foo () as string = "dBaz::foo") +;; diff --git a/Examples/test-suite/ocaml/template_inherit_runme.ml b/Examples/test-suite/ocaml/template_inherit_runme.ml new file mode 100644 index 000000000..1f3761cd2 --- /dev/null +++ b/Examples/test-suite/ocaml/template_inherit_runme.ml @@ -0,0 +1,22 @@ +open Swig +open Template_inherit + +let _ = + let a = new_FooInt '() and b = new_FooDouble '() and c = new_BarInt '() + and d = new_BarDouble '() and e = new_FooUInt '() and f = new_BarUInt '() in + assert (a -> blah () as string = "Foo"); + assert (b -> blah () as string = "Foo"); + assert (e -> blah () as string = "Foo"); + assert (c -> blah () as string = "Bar"); + assert (d -> blah () as string = "Bar"); + assert (f -> blah () as string = "Bar"); + assert (c -> foomethod () as string = "foomethod"); + assert (d -> foomethod () as string = "foomethod"); + assert (f -> foomethod () as string = "foomethod"); + assert (_invoke_blah_int '(a) as string = "Foo"); + assert (_invoke_blah_int '(c) as string = "Bar"); + assert (_invoke_blah_double '(b) as string = "Foo"); + assert (_invoke_blah_double '(d) as string = "Bar"); + assert (_invoke_blah_uint '(e) as string = "Foo"); + assert (_invoke_blah_uint '(f) as string = "Bar") +;; diff --git a/Examples/test-suite/ocaml/template_opaque_runme.ml b/Examples/test-suite/ocaml/template_opaque_runme.ml new file mode 100644 index 000000000..cb9e18905 --- /dev/null +++ b/Examples/test-suite/ocaml/template_opaque_runme.ml @@ -0,0 +1,5 @@ +open Swig +open Template_opaque + +let v = new_OpaqueVectorType (C_uint 10l) +let _ = _FillVector '(v) diff --git a/Examples/test-suite/ocaml/template_ref_type_runme.ml b/Examples/test-suite/ocaml/template_ref_type_runme.ml new file mode 100644 index 000000000..2db2f9b28 --- /dev/null +++ b/Examples/test-suite/ocaml/template_ref_type_runme.ml @@ -0,0 +1,6 @@ +open Swig +open Template_ref_type + +let xr = new_XC '() +let y = new_Y '() +let _ = y -> find (xr) diff --git a/Examples/test-suite/ocaml/template_rename_runme.ml b/Examples/test-suite/ocaml/template_rename_runme.ml new file mode 100644 index 000000000..be19aa107 --- /dev/null +++ b/Examples/test-suite/ocaml/template_rename_runme.ml @@ -0,0 +1,12 @@ +open Swig +open Template_rename + +let _ = + let i = new_iFoo '() and d = new_dFoo '() in + assert (i -> blah_test (4) as int = 4); + assert (i -> spam_test (5) as int = 5); + assert (i -> groki_test (6) as int = 6); + assert (d -> blah_test (7) as int = 7); + assert (d -> spam (8) as int = 8); + assert (d -> grok_test (9) as int = 9) +;; diff --git a/Examples/test-suite/ocaml/template_tbase_template_runme.ml b/Examples/test-suite/ocaml/template_tbase_template_runme.ml new file mode 100644 index 000000000..724776a24 --- /dev/null +++ b/Examples/test-suite/ocaml/template_tbase_template_runme.ml @@ -0,0 +1,5 @@ +open Swig +open Template_tbase_template + +let a = _make_Class_dd '() +assert (a -> test () as string = "test") diff --git a/Examples/test-suite/ocaml/throw_exception_runme.ml b/Examples/test-suite/ocaml/throw_exception_runme.ml index 8781926b6..5c4c0922a 100644 --- a/Examples/test-suite/ocaml/throw_exception_runme.ml +++ b/Examples/test-suite/ocaml/throw_exception_runme.ml @@ -1,28 +1,25 @@ -(* Throw exception test *) - open Swig open Throw_exception -let x = new_Foo C_void ;; -let _ = - try - (invoke x) "test_int" C_void - with (Failure "Exception(37): Thrown exception from C++ (int)\n") -> - try - (invoke x) "test_msg" C_void - with (Failure "Exception(0): Dead\n") -> - try - (invoke x) "test_cls" C_void - with (Failure "Exception(0): Thrown exception from C++ (unknown)\n") -> - try - (invoke x) "test_multi" (C_int 1) - with (Failure "Exception(37): Thrown exception from C++ (int)\n") -> - try - (invoke x) "test_multi" (C_int 2) - with (Failure "Exception(0): Dead\n") -> - try - (invoke x) "test_multi" (C_int 3) - with (Failure "Exception(0): Thrown exception from C++ (unknown)\n") -> - exit 0 +let x = new_Foo '() -let _ = exit 1 +let check meth args expected = + try + let _ = ((invoke x) meth (args)) in assert false + with Failure msg -> assert (msg = expected) + +let _ = + check "test_int" '() "C++ int exception thrown, value: 37"; + check "test_msg" '() "Dead"; + check "test_cls" '() "C++ CError exception thrown"; + check "test_cls_ptr" '() "C++ CError * exception thrown"; + check "test_cls_ref" '() "C++ CError & exception thrown"; + check "test_cls_td" '() "C++ Namespace::ErrorTypedef exception thrown"; + check "test_cls_ptr_td" '() "C++ Namespace::ErrorPtr exception thrown"; + check "test_cls_ref_td" '() "C++ Namespace::ErrorRef exception thrown"; + check "test_array" '() "C++ int [10] exception thrown"; + check "test_enum" '() "C++ Namespace::EnumTest exception thrown"; + check "test_multi" '(1) "C++ int exception thrown, value: 37"; + check "test_multi" '(2) "Dead"; + check "test_multi" '(3) "C++ CError exception thrown"; +;; diff --git a/Examples/test-suite/ocaml/typedef_class_runme.ml b/Examples/test-suite/ocaml/typedef_class_runme.ml new file mode 100644 index 000000000..969c3e420 --- /dev/null +++ b/Examples/test-suite/ocaml/typedef_class_runme.ml @@ -0,0 +1,13 @@ +open Swig +open Typedef_class + +let a = new_RealA '() +let _ = a -> "[a]" (3) + +let b = new_B '() +let _ = assert (b -> testA (a) as int = 3) + +let bb = new_BB '() +let bb2 = new_BB '(2) +let _ = assert (bb -> aa_method (1.) as int = 0) +let bbb = new_BBB '() diff --git a/Examples/test-suite/ocaml/typedef_classforward_same_name_runme.ml b/Examples/test-suite/ocaml/typedef_classforward_same_name_runme.ml new file mode 100644 index 000000000..304f74b7a --- /dev/null +++ b/Examples/test-suite/ocaml/typedef_classforward_same_name_runme.ml @@ -0,0 +1,11 @@ +open Swig +open Typedef_classforward_same_name + +let _ = + let foo = new_Foo '() in + ignore (foo -> "[x]" (5)); + assert (_extractFoo '(foo) as int = 5); + let boo = new_Boo '() in + ignore (boo -> "[x]" (5)); + assert (_extractBoo '(boo) as int = 5) +;; diff --git a/Examples/test-suite/ocaml/typedef_inherit_runme.ml b/Examples/test-suite/ocaml/typedef_inherit_runme.ml new file mode 100644 index 000000000..6352fd4ad --- /dev/null +++ b/Examples/test-suite/ocaml/typedef_inherit_runme.ml @@ -0,0 +1,11 @@ +open Swig +open Typedef_inherit + +let _ = + let a = new_Foo '() and b = new_Bar '() in + assert (_do_blah (a) as string = "Foo::blah"); + assert (_do_blah (b) as string = "Bar::blah"); + let c = new_Spam '() and d = new_Grok '() in + assert (_do_blah2 (c) as string = "Spam::blah"); + assert (_do_blah2 (d) as string = "Grok::blah") +;; diff --git a/Examples/test-suite/ocaml/typedef_mptr_runme.ml b/Examples/test-suite/ocaml/typedef_mptr_runme.ml index 3bdaac4ba..36aafe695 100644 --- a/Examples/test-suite/ocaml/typedef_mptr_runme.ml +++ b/Examples/test-suite/ocaml/typedef_mptr_runme.ml @@ -1,16 +1,13 @@ open Swig open Typedef_mptr -let soci x = (string_of_int (get_int x)) - -let x = new_Foo C_void -let add_res = _do_op (C_list [ x ; C_int 2 ; C_int 1 ; _add ]) -and sub_res = _do_op (C_list [ x ; C_int 2 ; C_int 1 ; _sub ]) let _ = - if add_res <> (C_int 3) || sub_res <> (C_int 1) then - raise (Failure ("Bad result:" ^ - " (add " ^ (soci add_res) ^ ") " ^ - " (sub " ^ (soci sub_res) ^ ")")) -let _ = Printf.printf "2 + 1 = %d, 2 - 1 = %d\n" - (get_int add_res) - (get_int sub_res) + let f = new_Foo '() in + let args = C_list [ C_int 2 ; C_int 1 ; _add '() ] in + assert (f -> do_op (args) as int = 3); + let args = C_list [ C_int 2 ; C_int 1 ; _sub '() ] in + assert (f -> do_op (args) as int = 1); + + assert (_do_op (C_list [ f ; C_int 2 ; C_int 1 ; _add '() ]) = C_int 3); + assert (_do_op (C_list [ f ; C_int 2 ; C_int 1 ; _sub '() ]) = C_int 1); +;; diff --git a/Examples/test-suite/ocaml/typedef_reference_runme.ml b/Examples/test-suite/ocaml/typedef_reference_runme.ml new file mode 100644 index 000000000..4c9cc6fca --- /dev/null +++ b/Examples/test-suite/ocaml/typedef_reference_runme.ml @@ -0,0 +1,11 @@ +open Swig +open Typedef_reference + +let _ = + let i = _copy_intp '(2) in + assert (_somefunc '(i) as int = 2); + assert (_delete_intp '(i) = C_void); + let i = _copy_intp '(3) in + assert (_otherfunc '(i) as int = 3); + assert (_delete_intp '(i) = C_void); +;; diff --git a/Examples/test-suite/ocaml/typemap_arrays_runme.ml b/Examples/test-suite/ocaml/typemap_arrays_runme.ml new file mode 100644 index 000000000..611e1d338 --- /dev/null +++ b/Examples/test-suite/ocaml/typemap_arrays_runme.ml @@ -0,0 +1,4 @@ +open Swig +open Typemap_arrays + +let _ = assert (_sumA '(0) as int = 60) diff --git a/Examples/test-suite/ocaml/typemap_delete_runme.ml b/Examples/test-suite/ocaml/typemap_delete_runme.ml new file mode 100644 index 000000000..0cffb025b --- /dev/null +++ b/Examples/test-suite/ocaml/typemap_delete_runme.ml @@ -0,0 +1,5 @@ +open Swig +open Typemap_delete + +let r = new_Rect '(123) +let _ = assert (r -> "[val]" () as int = 123) diff --git a/Examples/test-suite/ocaml/types_directive_runme.ml b/Examples/test-suite/ocaml/types_directive_runme.ml new file mode 100644 index 000000000..8503d00ff --- /dev/null +++ b/Examples/test-suite/ocaml/types_directive_runme.ml @@ -0,0 +1,14 @@ +open Swig +open Types_directive + +let _ = + (* Check that a Time1 instance is accepted where a Date instance is expected. *) + let d1 = new_Time1 '(2001, 2, 3, 60) in + let newDate = _add '(d1, 7) in + assert (newDate -> "[day]" () as int = 10); + + (* Check that a Time2 instance is accepted where a Date instance is expected. *) + let d2 = new_Time2 '(1999, 8, 7, 60) in + let newDate = _add '(d2, 7) in + assert (newDate -> "[day]" () as int = 14) +;; diff --git a/Examples/test-suite/ocaml/unions_runme.ml b/Examples/test-suite/ocaml/unions_runme.ml index cbf1628ac..c451cb2be 100644 --- a/Examples/test-suite/ocaml/unions_runme.ml +++ b/Examples/test-suite/ocaml/unions_runme.ml @@ -8,21 +8,21 @@ let b = new_BigStruct C_void let c = new_UnionTest C_void let d = new_EmbeddedUnionTest C_void -let _ = (invoke a) "jill" (C_short 3) -let _ = (invoke b) "jack" (C_char 'a') (* Int conversion *) -let _ = (invoke b) "smallstruct" a (* Put a in b *) -let _ = (invoke c) "bs" b +let _ = (invoke a) "[jill]" (C_short 3) +let _ = (invoke b) "[jack]" (C_char 'a') (* Int conversion *) +let _ = (invoke b) "[smallstruct]" a (* Put a in b *) +let _ = (invoke c) "[bs]" b -let _ = if get_int ((invoke a) "jill" C_void) != 3 then +let _ = if get_int ((invoke a) "[jill]" C_void) != 3 then raise (Failure "jill value is not preserved") -let _ = if get_int ((invoke b) "jack" C_void) != (int_of_char 'a') then +let _ = if get_int ((invoke b) "[jack]" C_void) != (int_of_char 'a') then raise (Failure "jack value is not preserved") -let _ = if get_int ((invoke ((invoke b) "smallstruct" C_void)) - "jill" C_void) != 3 then +let _ = if get_int ((invoke ((invoke b) "[smallstruct]" C_void)) + "[jill]" C_void) != 3 then raise (Failure "jill value is not embedded in bigstruct") -let _ = if get_int ((invoke ((invoke c) "bs" C_void)) - "jack" C_void) != (int_of_char 'a') then +let _ = if get_int ((invoke ((invoke c) "[bs]" C_void)) + "[jack]" C_void) != (int_of_char 'a') then raise (Failure "union set of bigstruct did not take") -let _ = if get_int ((invoke ((invoke c) "ss" C_void)) - "jill" C_void) != (int_of_char 'a') then +let _ = if get_int ((invoke ((invoke c) "[ss]" C_void)) + "[jill]" C_void) != (int_of_char 'a') then raise (Failure "corresponding union values are not the same") diff --git a/Examples/test-suite/ocaml/using1_runme.ml b/Examples/test-suite/ocaml/using1_runme.ml new file mode 100644 index 000000000..defda603c --- /dev/null +++ b/Examples/test-suite/ocaml/using1_runme.ml @@ -0,0 +1,4 @@ +open Swig +open Using1 + +let _ = assert (_spam '(37) as int = 37) diff --git a/Examples/test-suite/ocaml/using_extend_runme.ml b/Examples/test-suite/ocaml/using_extend_runme.ml new file mode 100644 index 000000000..0b7c57f65 --- /dev/null +++ b/Examples/test-suite/ocaml/using_extend_runme.ml @@ -0,0 +1,12 @@ +open Swig +open Using_extend + +let _ = + let f = new_FooBar '() in + assert (f -> blah (3) as int = 3); + assert (f -> blah (3.5) as float = 3.5); + assert (f -> blah ("hello") as string = "hello"); + assert (f -> blah (3, 4) as int = 7); + assert (f -> blah (3.5, 7.5) as float = 11.); + assert (f -> duh (3) as int = 3) +;; diff --git a/Examples/test-suite/ocaml/using_inherit_runme.ml b/Examples/test-suite/ocaml/using_inherit_runme.ml new file mode 100644 index 000000000..2c49c5e6f --- /dev/null +++ b/Examples/test-suite/ocaml/using_inherit_runme.ml @@ -0,0 +1,24 @@ +open Swig +open Using_inherit + +let _ = + let b = new_Bar '() in + assert (b -> test (3) as int = 3); + assert (b -> test (3.5) as float = 3.5); + let b = new_Bar2 '() in + assert (b -> test (3) as int = 6); + assert (b -> test (3.5) as float = 7.0); + let b = new_Bar3 '() in + assert (b -> test (3) as int = 6); + assert (b -> test (3.5) as float = 7.0); + let b = new_Bar4 '() in + assert (b -> test (3) as int = 6); + assert (b -> test (3.5) as float = 7.0); + + let f = new_Fred1 '() in + assert (f -> test (3) as int = 3); + assert (f -> test (3.5) as float = 7.0); + let f = new_Fred2 '() in + assert (f -> test (3) as int = 3); + assert (f -> test (3.5) as float = 7.0) +;; diff --git a/Examples/test-suite/ocaml/using_pointers_runme.ml b/Examples/test-suite/ocaml/using_pointers_runme.ml new file mode 100644 index 000000000..98fd3fb48 --- /dev/null +++ b/Examples/test-suite/ocaml/using_pointers_runme.ml @@ -0,0 +1,10 @@ +open Swig +open Using_pointers + +let f = new_FooBar '() +try + ignore (f -> exception_spec (1)); assert false +with Failure _ -> () +try + ignore (f -> exception_spec (2)); assert false +with Failure _ -> () diff --git a/Examples/test-suite/ocaml/using_private_runme.ml b/Examples/test-suite/ocaml/using_private_runme.ml new file mode 100644 index 000000000..026cbfd91 --- /dev/null +++ b/Examples/test-suite/ocaml/using_private_runme.ml @@ -0,0 +1,10 @@ +open Swig +open Using_private + +let _ = + let f = new_FooBar '() in + let _ = f -> "[x]" (3) in + assert (f -> blah (4) as int = 4); + assert (f -> defaulted () as int = -1); + assert (f -> defaulted (222) as int = 222) +;; diff --git a/Examples/test-suite/ocaml/using_protected_runme.ml b/Examples/test-suite/ocaml/using_protected_runme.ml index 4dc4fe1c9..29647c288 100644 --- a/Examples/test-suite/ocaml/using_protected_runme.ml +++ b/Examples/test-suite/ocaml/using_protected_runme.ml @@ -2,7 +2,7 @@ open Swig open Using_protected let f = new_FooBar C_void -let _ = (invoke f) "x" (C_int 3) +let _ = (invoke f) "[x]" (C_int 3) let _ = if (invoke f) "blah" (C_int 4) <> (C_int 4) then raise (Failure "blah(int)") diff --git a/Examples/test-suite/ocaml/valuewrapper_runme.ml b/Examples/test-suite/ocaml/valuewrapper_runme.ml new file mode 100644 index 000000000..0e2d73136 --- /dev/null +++ b/Examples/test-suite/ocaml/valuewrapper_runme.ml @@ -0,0 +1,8 @@ +open Swig +open Valuewrapper + +let _ = + let x1 = new_Xi '(5) and y1 = new_YXi '() in + assert (y1 -> spam (x1) as int = 0); + assert (y1 -> spam () as int = 0) +;; diff --git a/Examples/test-suite/ocaml/varargs_overload_runme.ml b/Examples/test-suite/ocaml/varargs_overload_runme.ml new file mode 100644 index 000000000..418f881e3 --- /dev/null +++ b/Examples/test-suite/ocaml/varargs_overload_runme.ml @@ -0,0 +1,29 @@ +open Swig +open Varargs_overload + +let _ = + assert (_vararg_over1 '("Hello") as string = "Hello"); + assert (_vararg_over1 '(2) as string = "2"); + assert (_vararg_over2 '("Hello") as string = "Hello"); + assert (_vararg_over2 '(2, 2.2) as string = "2 2.2"); + + assert (_vararg_over3 '("Hello") as string = "Hello"); + assert (_vararg_over3 '(2, 2.2, "hey") as string = "2 2.2 hey"); + assert (_vararg_over4 '("Hello") as string = "Hello"); + assert (_vararg_over4 '(123) as string = "123"); + assert (_vararg_over4 '("Hello", 123) as string = "Hello"); + + + (* Same as above but non-vararg function declared first *) + + assert (_vararg_over6 '("Hello") as string = "Hello"); + assert (_vararg_over6 '(2) as string = "2"); + assert (_vararg_over7 '("Hello") as string = "Hello"); + assert (_vararg_over7 '(2, 2.2) as string = "2 2.2"); + + assert (_vararg_over8 '("Hello") as string = "Hello"); + assert (_vararg_over8 '(2, 2.2, "hey") as string = "2 2.2 hey"); + assert (_vararg_over9 '("Hello") as string = "Hello"); + assert (_vararg_over9 '(123) as string = "123"); + assert (_vararg_over9 '("Hello", 123) as string = "Hello"); +;; diff --git a/Examples/test-suite/ocaml/wrapmacro_runme.ml b/Examples/test-suite/ocaml/wrapmacro_runme.ml new file mode 100644 index 000000000..f11136360 --- /dev/null +++ b/Examples/test-suite/ocaml/wrapmacro_runme.ml @@ -0,0 +1,10 @@ +open Swig +open Wrapmacro + +let _ = + let args = C_list [ C_int64 2L ; C_int64 1L ] in + assert (_maximum '(args) as int = 2); + let args = C_list [ C_double (2. /. 7.) ; C_double 256. ] in + assert (_maximum '(args) as float = 256.); + assert (_GUINT16_SWAP_LE_BE_CONSTANT '(0x1234) as int = 0x3412); +;; diff --git a/Examples/test-suite/octave/Makefile.in b/Examples/test-suite/octave/Makefile.in index be47904e2..3c8f3b165 100644 --- a/Examples/test-suite/octave/Makefile.in +++ b/Examples/test-suite/octave/Makefile.in @@ -16,6 +16,12 @@ CPP_TEST_CASES += \ octave_cell_deref\ octave_dim +CPP11_TEST_CASES += \ + cpp11_shared_ptr_const \ + cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ + cpp11_shared_ptr_upcast \ + CPP_TEST_BROKEN += \ implicittest \ li_implicit \ @@ -59,7 +65,7 @@ CSRCS = octave_empty.c # a file is found which has _runme.m appended after the testcase name. run_testcase = \ if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH OCTAVE_PATH=$(srcdir):$$OCTAVE_PATH $(RUNTOOL) $(OCTAVE) $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH OCTAVE_PATH=$(srcdir) OCTAVE_HISTFILE=/dev/null $(RUNTOOL) $(OCTAVE) $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ fi # Clean: remove the generated .m file @@ -70,20 +76,6 @@ run_testcase = \ clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' octave_clean -cvsignore: - @echo '*wrap* *.mc *.so *.dll *.exp *.lib' - @echo Makefile - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.m; done - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do if grep -q $${i}_runme.m CVS/Entries ; then echo $${i}_runme.m; fi; done - @echo clientdata_prop_a.m - @echo clientdata_prop_b.m - @echo imports_a.m - @echo imports_b.m - @echo mod_a.m mod_b.m - @echo hugemod.h hugemod_a.i hugemod_b.i hugemod_a.m hugemod_b.m hugemod_runme.m - @echo template_typedef_import.m - - hugemod: perl hugemod.pl $(MAKE) hugemod_a.cpptest diff --git a/Examples/test-suite/octave/abstract_typedef2_runme.m b/Examples/test-suite/octave/abstract_typedef2_runme.m index 7f364db4e..e2b41fed9 100644 --- a/Examples/test-suite/octave/abstract_typedef2_runme.m +++ b/Examples/test-suite/octave/abstract_typedef2_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + abstract_typedef2 a = A_UF(); diff --git a/Examples/test-suite/octave/abstract_typedef_runme.m b/Examples/test-suite/octave/abstract_typedef_runme.m index f28cf3c8b..e57f71504 100644 --- a/Examples/test-suite/octave/abstract_typedef_runme.m +++ b/Examples/test-suite/octave/abstract_typedef_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + abstract_typedef e = Engine(); diff --git a/Examples/test-suite/octave/abstract_virtual_runme.m b/Examples/test-suite/octave/abstract_virtual_runme.m index 9845a5885..d99ca1c74 100644 --- a/Examples/test-suite/octave/abstract_virtual_runme.m +++ b/Examples/test-suite/octave/abstract_virtual_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + abstract_virtual diff --git a/Examples/test-suite/octave/arrays_global_runme.m b/Examples/test-suite/octave/arrays_global_runme.m index 619d381b0..b4f23469f 100644 --- a/Examples/test-suite/octave/arrays_global_runme.m +++ b/Examples/test-suite/octave/arrays_global_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + arrays_global arrays_global.cvar.array_i = arrays_global.cvar.array_const_i; diff --git a/Examples/test-suite/octave/class_ignore_runme.m b/Examples/test-suite/octave/class_ignore_runme.m index 76bbcd3f0..3e52047c2 100644 --- a/Examples/test-suite/octave/class_ignore_runme.m +++ b/Examples/test-suite/octave/class_ignore_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + class_ignore a = class_ignore.Bar(); diff --git a/Examples/test-suite/octave/complextest_runme.m b/Examples/test-suite/octave/complextest_runme.m index cd0f9f4e2..cd9c4a8b7 100644 --- a/Examples/test-suite/octave/complextest_runme.m +++ b/Examples/test-suite/octave/complextest_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + complextest a = complex(-1,2); @@ -10,10 +15,16 @@ if (complextest.Conjf(a) != a.conjugate()) error("bad complex mapping") endif +if (complextest.Conj2(a) != a.conjugate()) + error("bad complex mapping") +endif + +if (complextest.Conjf2(a) != a.conjugate()) + error("bad complex mapping") +endif + v = (complex(1,2), complex(2,3), complex(4,3), 1); -try - complextest.Copy_h(v); -catch -end_try_catch +complextest.CopyHalf(v); +complextest.CopyHalfRef(v); diff --git a/Examples/test-suite/octave/constover_runme.m b/Examples/test-suite/octave/constover_runme.m index febcdae69..47fdb6f98 100644 --- a/Examples/test-suite/octave/constover_runme.m +++ b/Examples/test-suite/octave/constover_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + constover p = constover.test("test"); diff --git a/Examples/test-suite/octave/constructor_copy_runme.m b/Examples/test-suite/octave/constructor_copy_runme.m index 5d52ab525..e450214c6 100644 --- a/Examples/test-suite/octave/constructor_copy_runme.m +++ b/Examples/test-suite/octave/constructor_copy_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + constructor_copy f1 = Foo1(3); diff --git a/Examples/test-suite/octave/default_args_runme.m b/Examples/test-suite/octave/default_args_runme.m index f8a656003..3d00f63e0 100644 --- a/Examples/test-suite/octave/default_args_runme.m +++ b/Examples/test-suite/octave/default_args_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + default_args diff --git a/Examples/test-suite/octave/default_constructor_runme.m b/Examples/test-suite/octave/default_constructor_runme.m index ebe553b20..b0feaf561 100644 --- a/Examples/test-suite/octave/default_constructor_runme.m +++ b/Examples/test-suite/octave/default_constructor_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + default_constructor dc = default_constructor; diff --git a/Examples/test-suite/octave/director_abstract_runme.m b/Examples/test-suite/octave/director_abstract_runme.m index 00fb676f5..657e2e1d9 100644 --- a/Examples/test-suite/octave/director_abstract_runme.m +++ b/Examples/test-suite/octave/director_abstract_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + director_abstract MyFoo=@() subclass(director_abstract.Foo(),@ping); diff --git a/Examples/test-suite/octave/director_classic_runme.m b/Examples/test-suite/octave/director_classic_runme.m index c1f8e95d4..167c8eae9 100644 --- a/Examples/test-suite/octave/director_classic_runme.m +++ b/Examples/test-suite/octave/director_classic_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + director_classic TargetLangPerson=@() subclass(Person(),'id',@(self) "TargetLangPerson"); diff --git a/Examples/test-suite/octave/director_extend_runme.m b/Examples/test-suite/octave/director_extend_runme.m index 1cbeac8e2..3b23e566d 100644 --- a/Examples/test-suite/octave/director_extend_runme.m +++ b/Examples/test-suite/octave/director_extend_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + director_extend MyObject=@() subclass(SpObject(),'getFoo',@(self) 123); diff --git a/Examples/test-suite/octave/director_stl_runme.m b/Examples/test-suite/octave/director_stl_runme.m index e8f4c5e34..23990c2a2 100644 --- a/Examples/test-suite/octave/director_stl_runme.m +++ b/Examples/test-suite/octave/director_stl_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + director_stl MyFoo=@() subclass(director_stl.Foo(),\ diff --git a/Examples/test-suite/octave/director_string_runme.m b/Examples/test-suite/octave/director_string_runme.m index c2d4e9ce7..a078c26d7 100644 --- a/Examples/test-suite/octave/director_string_runme.m +++ b/Examples/test-suite/octave/director_string_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + director_string diff --git a/Examples/test-suite/octave/director_wstring_runme.m b/Examples/test-suite/octave/director_wstring_runme.m index b59ff6efa..99b8e992a 100644 --- a/Examples/test-suite/octave/director_wstring_runme.m +++ b/Examples/test-suite/octave/director_wstring_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + director_wstring diff --git a/Examples/test-suite/octave/dynamic_cast_runme.m b/Examples/test-suite/octave/dynamic_cast_runme.m index dad0ba25c..b53120bb5 100644 --- a/Examples/test-suite/octave/dynamic_cast_runme.m +++ b/Examples/test-suite/octave/dynamic_cast_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + dynamic_cast f = dynamic_cast.Foo(); diff --git a/Examples/test-suite/octave/empty_c_runme.m b/Examples/test-suite/octave/empty_c_runme.m index 81264deb1..9ff6572da 100644 --- a/Examples/test-suite/octave/empty_c_runme.m +++ b/Examples/test-suite/octave/empty_c_runme.m @@ -1,2 +1,7 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + empty_c diff --git a/Examples/test-suite/octave/empty_runme.m b/Examples/test-suite/octave/empty_runme.m index e7b64f1cd..10f72a2d2 100644 --- a/Examples/test-suite/octave/empty_runme.m +++ b/Examples/test-suite/octave/empty_runme.m @@ -1,2 +1,7 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + empty diff --git a/Examples/test-suite/octave/enum_template_runme.m b/Examples/test-suite/octave/enum_template_runme.m index ca10f1f37..a9f940a9f 100644 --- a/Examples/test-suite/octave/enum_template_runme.m +++ b/Examples/test-suite/octave/enum_template_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + enum_template if (enum_template.MakeETest() != 1) diff --git a/Examples/test-suite/octave/exception_order_runme.m b/Examples/test-suite/octave/exception_order_runme.m index 5ef85f46c..b352d5268 100644 --- a/Examples/test-suite/octave/exception_order_runme.m +++ b/Examples/test-suite/octave/exception_order_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + exception_order function check_lasterror(expected) diff --git a/Examples/test-suite/octave/extend_template_ns_runme.m b/Examples/test-suite/octave/extend_template_ns_runme.m index 401ea6327..e79a00dda 100644 --- a/Examples/test-suite/octave/extend_template_ns_runme.m +++ b/Examples/test-suite/octave/extend_template_ns_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + extend_template_ns f = Foo_One(); diff --git a/Examples/test-suite/octave/friends_runme.m b/Examples/test-suite/octave/friends_runme.m index e18f47a24..31211567f 100644 --- a/Examples/test-suite/octave/friends_runme.m +++ b/Examples/test-suite/octave/friends_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + friends a = friends.A(2); diff --git a/Examples/test-suite/octave/global_ns_arg_runme.m b/Examples/test-suite/octave/global_ns_arg_runme.m index b8f7cfa31..bd90b6409 100644 --- a/Examples/test-suite/octave/global_ns_arg_runme.m +++ b/Examples/test-suite/octave/global_ns_arg_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + global_ns_arg a = foo(1); diff --git a/Examples/test-suite/octave/grouping_runme.m b/Examples/test-suite/octave/grouping_runme.m index 26b896c2b..6d1a2d673 100644 --- a/Examples/test-suite/octave/grouping_runme.m +++ b/Examples/test-suite/octave/grouping_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + grouping x = grouping.test1(42); diff --git a/Examples/test-suite/octave/input_runme.m b/Examples/test-suite/octave/input_runme.m index 757862179..1a92d032b 100644 --- a/Examples/test-suite/octave/input_runme.m +++ b/Examples/test-suite/octave/input_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + input f = Foo(); diff --git a/Examples/test-suite/octave/li_attribute_runme.m b/Examples/test-suite/octave/li_attribute_runme.m index 548e733ed..ed051d9df 100644 --- a/Examples/test-suite/octave/li_attribute_runme.m +++ b/Examples/test-suite/octave/li_attribute_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_attribute aa = li_attribute.A(1,2,3); diff --git a/Examples/test-suite/octave/li_boost_shared_ptr_runme.m b/Examples/test-suite/octave/li_boost_shared_ptr_runme.m index 1da0a5725..b6d545564 100644 --- a/Examples/test-suite/octave/li_boost_shared_ptr_runme.m +++ b/Examples/test-suite/octave/li_boost_shared_ptr_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + 1; li_boost_shared_ptr; diff --git a/Examples/test-suite/octave/li_carrays_cpp_runme.m b/Examples/test-suite/octave/li_carrays_cpp_runme.m index d5b92139e..b3b520920 100644 --- a/Examples/test-suite/octave/li_carrays_cpp_runme.m +++ b/Examples/test-suite/octave/li_carrays_cpp_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_carrays_cpp d = doubleArray(10); diff --git a/Examples/test-suite/octave/li_carrays_runme.m b/Examples/test-suite/octave/li_carrays_runme.m index 8ec7e5911..c6b5f1619 100644 --- a/Examples/test-suite/octave/li_carrays_runme.m +++ b/Examples/test-suite/octave/li_carrays_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_carrays d = doubleArray(10); diff --git a/Examples/test-suite/octave/li_cmalloc_runme.m b/Examples/test-suite/octave/li_cmalloc_runme.m index 45faf7381..92bcd9515 100644 --- a/Examples/test-suite/octave/li_cmalloc_runme.m +++ b/Examples/test-suite/octave/li_cmalloc_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_cmalloc p = malloc_int(); diff --git a/Examples/test-suite/octave/li_cpointer_runme.m b/Examples/test-suite/octave/li_cpointer_runme.m index bf660a647..ce055cddd 100644 --- a/Examples/test-suite/octave/li_cpointer_runme.m +++ b/Examples/test-suite/octave/li_cpointer_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_cpointer diff --git a/Examples/test-suite/octave/li_cstring_runme.m b/Examples/test-suite/octave/li_cstring_runme.m index 0d2bdb73d..8aea6b709 100644 --- a/Examples/test-suite/octave/li_cstring_runme.m +++ b/Examples/test-suite/octave/li_cstring_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_cstring diff --git a/Examples/test-suite/octave/li_cwstring_runme.m b/Examples/test-suite/octave/li_cwstring_runme.m index 4cfef7fb5..1fb0962e7 100644 --- a/Examples/test-suite/octave/li_cwstring_runme.m +++ b/Examples/test-suite/octave/li_cwstring_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_cwstring if (count("ab\0ab\0ab\0", 0) != 3) diff --git a/Examples/test-suite/octave/li_factory_runme.m b/Examples/test-suite/octave/li_factory_runme.m index d87920da6..5ea9b779f 100644 --- a/Examples/test-suite/octave/li_factory_runme.m +++ b/Examples/test-suite/octave/li_factory_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_factory circle = Geometry_create(Geometry.CIRCLE); diff --git a/Examples/test-suite/octave/li_implicit_runme.m b/Examples/test-suite/octave/li_implicit_runme.m index 2ca8b59bf..dd4393a28 100644 --- a/Examples/test-suite/octave/li_implicit_runme.m +++ b/Examples/test-suite/octave/li_implicit_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_implicit b = B(); ai = A(1); diff --git a/Examples/test-suite/octave/li_std_pair_extra_runme.m b/Examples/test-suite/octave/li_std_pair_extra_runme.m index 0f9e9a23d..473b5e46d 100644 --- a/Examples/test-suite/octave/li_std_pair_extra_runme.m +++ b/Examples/test-suite/octave/li_std_pair_extra_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_std_pair_extra p = {1,2}; diff --git a/Examples/test-suite/octave/li_std_vector_enum_runme.m b/Examples/test-suite/octave/li_std_vector_enum_runme.m index 471e7bf39..0de77044d 100644 --- a/Examples/test-suite/octave/li_std_vector_enum_runme.m +++ b/Examples/test-suite/octave/li_std_vector_enum_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + li_std_vector_enum function check(a, b) diff --git a/Examples/test-suite/octave/li_std_wstring_runme.m b/Examples/test-suite/octave/li_std_wstring_runme.m deleted file mode 100644 index e46c1f219..000000000 --- a/Examples/test-suite/octave/li_std_wstring_runme.m +++ /dev/null @@ -1,90 +0,0 @@ -li_std_wstring - -x="h"; - -if (li_std_wstring.test_wcvalue(x) != x) - error("bad string mapping") -endif - -x="hello"; -if (li_std_wstring.test_ccvalue(x) != x) - error("bad string mapping") -endif - -if (li_std_wstring.test_cvalue(x) != x) - error("bad string mapping") -endif - -if (li_std_wstring.test_value(x) != x) - error("bad string mapping") -endif - -if (li_std_wstring.test_const_reference(x) != x) - error("bad string mapping") -endif - - -s = li_std_wstring.wstring("he"); -s = s + "llo"; - -if (s != x) - error("bad string mapping") -endif - -if (s(1:4) != x(1:4)) - error("bad string mapping") -endif - -if (li_std_wstring.test_value(s) != x) - error("bad string mapping") -endif - -if (li_std_wstring.test_const_reference(s) != x) - error("bad string mapping") -endif - -a = li_std_wstring.A(s); - -if (li_std_wstring.test_value(a) != x) - error("bad string mapping") -endif - -if (li_std_wstring.test_const_reference(a) != x) - error("bad string mapping") -endif - -b = li_std_wstring.wstring(" world"); - -if (a + b != "hello world") - error("bad string mapping") -endif - -if (a + " world" != "hello world") - error("bad string mapping") -endif - -if ("hello" + b != "hello world") - error("bad string mapping") -endif - -c = "hello" + b; -if (c.find_last_of("l") != 9) - error("bad string mapping") -endif - -s = "hello world"; - -b = li_std_wstring.B("hi"); - -b.name = li_std_wstring.wstring("hello"); -if (b.name != "hello") - error("bad string mapping") -endif - - -b.a = li_std_wstring.A("hello"); -if (b.a != "hello") - error("bad string mapping") -endif - - diff --git a/Examples/test-suite/octave/minherit_runme.m b/Examples/test-suite/octave/minherit_runme.m index 24d2091be..025db8ad2 100644 --- a/Examples/test-suite/octave/minherit_runme.m +++ b/Examples/test-suite/octave/minherit_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + minherit a = minherit.Foo(); diff --git a/Examples/test-suite/octave/mod_runme.m b/Examples/test-suite/octave/mod_runme.m index faebf70e3..6120eee4f 100644 --- a/Examples/test-suite/octave/mod_runme.m +++ b/Examples/test-suite/octave/mod_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + mod_a mod_b diff --git a/Examples/test-suite/octave/multi_import_runme.m b/Examples/test-suite/octave/multi_import_runme.m index 08149aae4..2b7a610d4 100644 --- a/Examples/test-suite/octave/multi_import_runme.m +++ b/Examples/test-suite/octave/multi_import_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + multi_import_a; multi_import_b; diff --git a/Examples/test-suite/octave/naturalvar_runme.m b/Examples/test-suite/octave/naturalvar_runme.m index 889563f35..6059b0273 100644 --- a/Examples/test-suite/octave/naturalvar_runme.m +++ b/Examples/test-suite/octave/naturalvar_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + naturalvar f = Foo(); diff --git a/Examples/test-suite/octave/null_pointer_runme.m b/Examples/test-suite/octave/null_pointer_runme.m index 51b6eaf91..72362f451 100644 --- a/Examples/test-suite/octave/null_pointer_runme.m +++ b/Examples/test-suite/octave/null_pointer_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + null_pointer; -assert(func([])); +assert(funk([])); diff --git a/Examples/test-suite/octave/octave_cell_deref_runme.m b/Examples/test-suite/octave/octave_cell_deref_runme.m index 5a98c0a3b..0a45999d3 100644 --- a/Examples/test-suite/octave/octave_cell_deref_runme.m +++ b/Examples/test-suite/octave/octave_cell_deref_runme.m @@ -1,7 +1,12 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + octave_cell_deref; -assert(func("hello")); -assert(func({"hello"})); +assert(funk("hello")); +assert(funk({"hello"})); c = func2(); assert(strcmp(c{1}, "hello")); diff --git a/Examples/test-suite/octave/overload_complicated_runme.m b/Examples/test-suite/octave/overload_complicated_runme.m index 0313be954..bbfc7ba19 100644 --- a/Examples/test-suite/octave/overload_complicated_runme.m +++ b/Examples/test-suite/octave/overload_complicated_runme.m @@ -1,14 +1,19 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + overload_complicated -pInt = None; +pInt = []; # NULL # Check the correct constructors are available p = Pop(pInt); -p = Pop(pInt, 0); +p = Pop(pInt, false); # Check overloaded in const only and pointers/references which target languages cannot disambiguate -if (p.hip(0) != 701) +if (p.hip(false) != 701) error("Test 1 failed") endif @@ -21,16 +26,16 @@ if (p.hop(pInt) != 805) error("Test 3 failed") endif -if (p.hop(0) != 801) +if (p.hop(false) != 801) error("Test 4 failed") endif # Few more variations and order shuffled -if (p.pop(0) != 901) +if (p.pop(false) != 901) error("Test 5 failed") endif -if (p.pop(pInt) != 902) +if (p.pop(pInt) != 904) error("Test 6 failed") endif @@ -43,12 +48,12 @@ if (p.bop(pInt) != 1001) error("Test 8 failed") endif -if (p.bip(pInt) != 2001) +if (p.bip(pInt) != 2002) error("Test 9 failed") endif # Globals -if (muzak(0) != 3001) +if (muzak(false) != 3001) error("Test 10 failed") endif diff --git a/Examples/test-suite/octave/overload_extend_c_runme.m b/Examples/test-suite/octave/overload_extend_c_runme.m index aa6bb5b5b..79b92ca47 100644 --- a/Examples/test-suite/octave/overload_extend_c_runme.m +++ b/Examples/test-suite/octave/overload_extend_c_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + overload_extend_c f = overload_extend_c.Foo(); diff --git a/Examples/test-suite/octave/overload_extend_runme.m b/Examples/test-suite/octave/overload_extend_runme.m index 42c79388f..d9959804f 100644 --- a/Examples/test-suite/octave/overload_extend_runme.m +++ b/Examples/test-suite/octave/overload_extend_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + overload_extend f = overload_extend.Foo(); diff --git a/Examples/test-suite/octave/overload_null_runme.m b/Examples/test-suite/octave/overload_null_runme.m new file mode 100644 index 000000000..a7c346c26 --- /dev/null +++ b/Examples/test-suite/octave/overload_null_runme.m @@ -0,0 +1,52 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + +overload_null + +function check(a, b) + if (a != b) + error("%i does not equal %i", a, b); + endif +end + +o = Overload(); +x = X(); +null = []; # NULL pointer + +check(1, o.byval1(x)); +check(2, o.byval1(null)); + +check(3, o.byval2(null)); +check(4, o.byval2(x)); + +check(5, o.byref1(x)); +check(6, o.byref1(null)); + +check(7, o.byref2(null)); +check(8, o.byref2(x)); + +check(9, o.byconstref1(x)); +check(10, o.byconstref1(null)); + +check(11, o.byconstref2(null)); +check(12, o.byconstref2(x)); + +# const pointer references +check(13, o.byval1cpr(x)); +check(14, o.byval1cpr(null)); + +check(15, o.byval2cpr(null)); +check(16, o.byval2cpr(x)); + +# forward class declaration +check(17, o.byval1forwardptr(x)); +check(18, o.byval1forwardptr(null)); + +check(19, o.byval2forwardptr(null)); +check(20, o.byval2forwardptr(x)); + +check(21, o.byval1forwardref(x)); + +check(22, o.byval2forwardref(x)); diff --git a/Examples/test-suite/octave/overload_simple_cast_runme.m b/Examples/test-suite/octave/overload_simple_cast_runme.m index 65bc4229a..218351082 100644 --- a/Examples/test-suite/octave/overload_simple_cast_runme.m +++ b/Examples/test-suite/octave/overload_simple_cast_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + overload_simple_cast Ai=@(x) subclass('x',x,'__int',@(self) self.x); diff --git a/Examples/test-suite/octave/overload_subtype_runme.m b/Examples/test-suite/octave/overload_subtype_runme.m index b34be9734..d1b209139 100644 --- a/Examples/test-suite/octave/overload_subtype_runme.m +++ b/Examples/test-suite/octave/overload_subtype_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + overload_subtype f = Foo(); diff --git a/Examples/test-suite/octave/preproc_runme.m b/Examples/test-suite/octave/preproc_runme.m index 791b38bf4..e9af66e78 100644 --- a/Examples/test-suite/octave/preproc_runme.m +++ b/Examples/test-suite/octave/preproc_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + preproc if (preproc.cvar.endif != 1) diff --git a/Examples/test-suite/octave/refcount_runme.m b/Examples/test-suite/octave/refcount_runme.m index 3ce5bcda2..9fc01e293 100644 --- a/Examples/test-suite/octave/refcount_runme.m +++ b/Examples/test-suite/octave/refcount_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + refcount # # very innocent example diff --git a/Examples/test-suite/octave/ret_by_value_runme.m b/Examples/test-suite/octave/ret_by_value_runme.m index d17c9f233..67f80aae2 100644 --- a/Examples/test-suite/octave/ret_by_value_runme.m +++ b/Examples/test-suite/octave/ret_by_value_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + ret_by_value a = ret_by_value.get_test(); diff --git a/Examples/test-suite/octave/return_const_value_runme.m b/Examples/test-suite/octave/return_const_value_runme.m index 1219c9293..8b363f297 100644 --- a/Examples/test-suite/octave/return_const_value_runme.m +++ b/Examples/test-suite/octave/return_const_value_runme.m @@ -2,10 +2,10 @@ return_const_value p = return_const_value.Foo_ptr.getPtr(); if (p.getVal() != 17) - error("Runtime test1 faild. p.getVal()=", p.getVal()) + error("Runtime test1 failed. p.getVal()=", p.getVal()) endif p = return_const_value.Foo_ptr.getConstPtr(); if (p.getVal() != 17) - error("Runtime test2 faild. p.getVal()=", p.getVal()) + error("Runtime test2 failed. p.getVal()=", p.getVal()) endif diff --git a/Examples/test-suite/octave/smart_pointer_extend_runme.m b/Examples/test-suite/octave/smart_pointer_extend_runme.m index c30cd9ff8..6c9258e6d 100644 --- a/Examples/test-suite/octave/smart_pointer_extend_runme.m +++ b/Examples/test-suite/octave/smart_pointer_extend_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + smart_pointer_extend f = Foo(); diff --git a/Examples/test-suite/octave/smart_pointer_overload_runme.m b/Examples/test-suite/octave/smart_pointer_overload_runme.m index 214437d66..a5df0ded4 100644 --- a/Examples/test-suite/octave/smart_pointer_overload_runme.m +++ b/Examples/test-suite/octave/smart_pointer_overload_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + smart_pointer_overload f = Foo(); diff --git a/Examples/test-suite/octave/smart_pointer_rename_runme.m b/Examples/test-suite/octave/smart_pointer_rename_runme.m index 260ee3e4c..5eb6d4c3c 100644 --- a/Examples/test-suite/octave/smart_pointer_rename_runme.m +++ b/Examples/test-suite/octave/smart_pointer_rename_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + smart_pointer_rename f = Foo(); diff --git a/Examples/test-suite/octave/smart_pointer_simple_runme.m b/Examples/test-suite/octave/smart_pointer_simple_runme.m index 26f32e04f..30b1387c4 100644 --- a/Examples/test-suite/octave/smart_pointer_simple_runme.m +++ b/Examples/test-suite/octave/smart_pointer_simple_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + smart_pointer_simple f = Foo(); diff --git a/Examples/test-suite/octave/smart_pointer_typedef_runme.m b/Examples/test-suite/octave/smart_pointer_typedef_runme.m index 8fa6ca26a..0e1c8a61e 100644 --- a/Examples/test-suite/octave/smart_pointer_typedef_runme.m +++ b/Examples/test-suite/octave/smart_pointer_typedef_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + smart_pointer_typedef f = Foo(); diff --git a/Examples/test-suite/octave/sneaky1_runme.m b/Examples/test-suite/octave/sneaky1_runme.m index e044370ea..dfbbf821b 100644 --- a/Examples/test-suite/octave/sneaky1_runme.m +++ b/Examples/test-suite/octave/sneaky1_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + sneaky1 x = sneaky1.add(3,4); y = sneaky1.subtract(3,4); diff --git a/Examples/test-suite/octave/static_const_member_2_runme.m b/Examples/test-suite/octave/static_const_member_2_runme.m index b242bfcd1..73260bae7 100644 --- a/Examples/test-suite/octave/static_const_member_2_runme.m +++ b/Examples/test-suite/octave/static_const_member_2_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + static_const_member_2 c = Test_int(); diff --git a/Examples/test-suite/octave/std_containers_runme.m b/Examples/test-suite/octave/std_containers_runme.m index 074f0fd58..eae3d5d9f 100644 --- a/Examples/test-suite/octave/std_containers_runme.m +++ b/Examples/test-suite/octave/std_containers_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + std_containers diff --git a/Examples/test-suite/octave/struct_value_runme.m b/Examples/test-suite/octave/struct_value_runme.m index 7340a36ec..ff344047e 100644 --- a/Examples/test-suite/octave/struct_value_runme.m +++ b/Examples/test-suite/octave/struct_value_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + struct_value b = struct_value.Bar(); diff --git a/Examples/test-suite/octave/swigobject_runme.m b/Examples/test-suite/octave/swigobject_runme.m index 614e2a44a..73167e497 100644 --- a/Examples/test-suite/octave/swigobject_runme.m +++ b/Examples/test-suite/octave/swigobject_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + swigobject a = A(); diff --git a/Examples/test-suite/octave/template_default_arg_runme.m b/Examples/test-suite/octave/template_default_arg_runme.m index e50066248..b2022167c 100644 --- a/Examples/test-suite/octave/template_default_arg_runme.m +++ b/Examples/test-suite/octave/template_default_arg_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_default_arg diff --git a/Examples/test-suite/octave/template_extend1_runme.m b/Examples/test-suite/octave/template_extend1_runme.m index e672da783..5035debf5 100644 --- a/Examples/test-suite/octave/template_extend1_runme.m +++ b/Examples/test-suite/octave/template_extend1_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_extend1 a = template_extend1.lBaz(); diff --git a/Examples/test-suite/octave/template_extend2_runme.m b/Examples/test-suite/octave/template_extend2_runme.m index 93c44d7de..24472a9ed 100644 --- a/Examples/test-suite/octave/template_extend2_runme.m +++ b/Examples/test-suite/octave/template_extend2_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_extend2 a = template_extend2.lBaz(); diff --git a/Examples/test-suite/octave/template_inherit_runme.m b/Examples/test-suite/octave/template_inherit_runme.m index ce7931e1c..368cce227 100644 --- a/Examples/test-suite/octave/template_inherit_runme.m +++ b/Examples/test-suite/octave/template_inherit_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_inherit a = FooInt(); b = FooDouble(); diff --git a/Examples/test-suite/octave/template_matrix_runme.m b/Examples/test-suite/octave/template_matrix_runme.m index b8fb3d3dc..96e7bd929 100644 --- a/Examples/test-suite/octave/template_matrix_runme.m +++ b/Examples/test-suite/octave/template_matrix_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_matrix passVector([1,2,3]); passMatrix({[1,2],[1,2,3]}); diff --git a/Examples/test-suite/octave/template_ns4_runme.m b/Examples/test-suite/octave/template_ns4_runme.m index 58ced7ca4..b5746427b 100644 --- a/Examples/test-suite/octave/template_ns4_runme.m +++ b/Examples/test-suite/octave/template_ns4_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_ns4 d = make_Class_DD(); diff --git a/Examples/test-suite/octave/template_opaque_runme.m b/Examples/test-suite/octave/template_opaque_runme.m index 1c123b334..4e8511ed4 100644 --- a/Examples/test-suite/octave/template_opaque_runme.m +++ b/Examples/test-suite/octave/template_opaque_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_opaque v = template_opaque.OpaqueVectorType(10); diff --git a/Examples/test-suite/octave/template_ref_type_runme.m b/Examples/test-suite/octave/template_ref_type_runme.m index ef77e06d9..9135fb03d 100644 --- a/Examples/test-suite/octave/template_ref_type_runme.m +++ b/Examples/test-suite/octave/template_ref_type_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_ref_type xr = template_ref_type.XC(); diff --git a/Examples/test-suite/octave/template_static_runme.m b/Examples/test-suite/octave/template_static_runme.m index c54139ae5..8d22feda5 100644 --- a/Examples/test-suite/octave/template_static_runme.m +++ b/Examples/test-suite/octave/template_static_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_static Foo_bar_double(1); diff --git a/Examples/test-suite/octave/template_typedef_cplx2_runme.m b/Examples/test-suite/octave/template_typedef_cplx2_runme.m index 94d3beb79..a72e0f1e0 100644 --- a/Examples/test-suite/octave/template_typedef_cplx2_runme.m +++ b/Examples/test-suite/octave/template_typedef_cplx2_runme.m @@ -12,7 +12,7 @@ catch error("is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(d)) != 1) +if (strfind('ArithUnaryFunction',swig_type(d)) != 1) d error("is not an ArithUnaryFunction") error @@ -26,7 +26,7 @@ catch error("is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(e)) != 1) +if (strfind('ArithUnaryFunction',swig_type(e)) != 1) e error("is not an ArithUnaryFunction") endif @@ -44,7 +44,7 @@ catch error("is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(c)) != 1) +if (strfind('ArithUnaryFunction',swig_type(c)) != 1) c error("is not an ArithUnaryFunction") endif @@ -57,7 +57,7 @@ catch error("is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(f)) != 1) +if (strfind('ArithUnaryFunction',swig_type(f)) != 1) f error("is not an ArithUnaryFunction") endif @@ -74,7 +74,7 @@ catch error("is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(g)) != 1) +if (strfind('ArithUnaryFunction',swig_type(g)) != 1) g error("is not an ArithUnaryFunction") error @@ -89,7 +89,7 @@ catch error("is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(h)) == -1) +if (strfind('ArithUnaryFunction',swig_type(h)) == -1) h error("is not an ArithUnaryFunction") endif diff --git a/Examples/test-suite/octave/template_typedef_cplx4_runme.m b/Examples/test-suite/octave/template_typedef_cplx4_runme.m index 4db276de4..e0c9a3277 100644 --- a/Examples/test-suite/octave/template_typedef_cplx4_runme.m +++ b/Examples/test-suite/octave/template_typedef_cplx4_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_typedef_cplx4 # diff --git a/Examples/test-suite/octave/template_typedef_cplx_runme.m b/Examples/test-suite/octave/template_typedef_cplx_runme.m index d00981cec..9e3e3888f 100644 --- a/Examples/test-suite/octave/template_typedef_cplx_runme.m +++ b/Examples/test-suite/octave/template_typedef_cplx_runme.m @@ -12,7 +12,7 @@ catch error("is not an instance") end_try_catch -if (findstr("ArithUnaryFunction",swig_type(d)) != 1) +if (strfind("ArithUnaryFunction",swig_type(d)) != 1) d error("is not an ArithUnaryFunction") endif @@ -24,7 +24,7 @@ catch error(e, "is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(e)) != 1); +if (strfind('ArithUnaryFunction',swig_type(e)) != 1); c error("is not an ArithUnaryFunction") endif @@ -42,7 +42,7 @@ catch error("is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(c)) != 1) +if (strfind('ArithUnaryFunction',swig_type(c)) != 1) c error("is not an ArithUnaryFunction") endif @@ -55,7 +55,7 @@ catch error("is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(f)) != 1) +if (strfind('ArithUnaryFunction',swig_type(f)) != 1) f error("is not an ArithUnaryFunction") endif @@ -72,7 +72,7 @@ catch error("is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(g)) != 1) +if (strfind('ArithUnaryFunction',swig_type(g)) != 1) g error("is not an ArithUnaryFunction") endif @@ -86,7 +86,7 @@ catch error("is not an instance") end_try_catch -if (findstr('ArithUnaryFunction',swig_type(h)) != 1) +if (strfind('ArithUnaryFunction',swig_type(h)) != 1) h error("is not an ArithUnaryFunction") endif diff --git a/Examples/test-suite/octave/template_typedef_import_runme.m b/Examples/test-suite/octave/template_typedef_import_runme.m index 0574ab1fc..0b3f215a8 100644 --- a/Examples/test-suite/octave/template_typedef_import_runme.m +++ b/Examples/test-suite/octave/template_typedef_import_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + template_typedef_cplx2 template_typedef_import diff --git a/Examples/test-suite/octave/typedef_class_runme.m b/Examples/test-suite/octave/typedef_class_runme.m index 97d2aed6a..55878a299 100644 --- a/Examples/test-suite/octave/typedef_class_runme.m +++ b/Examples/test-suite/octave/typedef_class_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + typedef_class a = typedef_class.RealA(); diff --git a/Examples/test-suite/octave/typedef_inherit_runme.m b/Examples/test-suite/octave/typedef_inherit_runme.m index 6c4c47a43..fbe5436d1 100644 --- a/Examples/test-suite/octave/typedef_inherit_runme.m +++ b/Examples/test-suite/octave/typedef_inherit_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + typedef_inherit a = typedef_inherit.Foo(); diff --git a/Examples/test-suite/octave/typename_runme.m b/Examples/test-suite/octave/typename_runme.m index c47f817a7..305cd4113 100644 --- a/Examples/test-suite/octave/typename_runme.m +++ b/Examples/test-suite/octave/typename_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + typename f = typename.Foo(); b = typename.Bar(); diff --git a/Examples/test-suite/octave/using1_runme.m b/Examples/test-suite/octave/using1_runme.m index 0c37daf7f..9253a1d35 100644 --- a/Examples/test-suite/octave/using1_runme.m +++ b/Examples/test-suite/octave/using1_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + using1 if (using1.spam(37) != 37) diff --git a/Examples/test-suite/octave/using2_runme.m b/Examples/test-suite/octave/using2_runme.m index 205c6d7ad..7cc668940 100644 --- a/Examples/test-suite/octave/using2_runme.m +++ b/Examples/test-suite/octave/using2_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + using2 if (using2.spam(37) != 37) diff --git a/Examples/test-suite/octave/using_composition_runme.m b/Examples/test-suite/octave/using_composition_runme.m index 9b58d6d54..63192ad77 100644 --- a/Examples/test-suite/octave/using_composition_runme.m +++ b/Examples/test-suite/octave/using_composition_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + using_composition f = FooBar(); diff --git a/Examples/test-suite/octave/using_extend_runme.m b/Examples/test-suite/octave/using_extend_runme.m index b9c13fa68..9b8f402d7 100644 --- a/Examples/test-suite/octave/using_extend_runme.m +++ b/Examples/test-suite/octave/using_extend_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + using_extend f = FooBar(); diff --git a/Examples/test-suite/octave/using_protected_runme.m b/Examples/test-suite/octave/using_protected_runme.m index ed4b1c32b..b5138c129 100644 --- a/Examples/test-suite/octave/using_protected_runme.m +++ b/Examples/test-suite/octave/using_protected_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + using_protected f = FooBar(); diff --git a/Examples/test-suite/octave/voidtest_runme.m b/Examples/test-suite/octave/voidtest_runme.m index e62f8a57f..fb411ee4e 100644 --- a/Examples/test-suite/octave/voidtest_runme.m +++ b/Examples/test-suite/octave/voidtest_runme.m @@ -1,3 +1,8 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + voidtest voidtest.globalfunc(); diff --git a/Examples/test-suite/octave_cell_deref.i b/Examples/test-suite/octave_cell_deref.i index 2e92ec4de..272ba7c99 100644 --- a/Examples/test-suite/octave_cell_deref.i +++ b/Examples/test-suite/octave_cell_deref.i @@ -1,7 +1,7 @@ %module octave_cell_deref %inline { - bool func(const char* s) { + bool funk(const char* s) { return !strcmp("hello",s); } diff --git a/Examples/test-suite/overload_arrays.i b/Examples/test-suite/overload_arrays.i index 42c08390a..272c96a3d 100644 --- a/Examples/test-suite/overload_arrays.i +++ b/Examples/test-suite/overload_arrays.i @@ -18,9 +18,10 @@ %rename(Foos) Foo; #endif +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) type; +#endif - -#ifndef SWIG_NO_OVERLOAD %immutable Spam::type; %inline %{ @@ -130,8 +131,6 @@ static char *bar(void *[SIZE]) { %} -#endif - %inline { class ClassA diff --git a/Examples/test-suite/overload_complicated.i b/Examples/test-suite/overload_complicated.i index 63ed32b3a..08abaaed6 100644 --- a/Examples/test-suite/overload_complicated.i +++ b/Examples/test-suite/overload_complicated.i @@ -1,27 +1,27 @@ // A complicated test of overloaded functions %module overload_complicated -#ifndef SWIG_NO_OVERLOAD - -// Different warning filters needed for scripting languages (eg Python) and for statically typed languages (eg C#). -%warnfilter(509, 516) Pop::Pop; // Overloaded xxxx is shadowed by xxxx at xxx:y. | Overloaded method xxxx ignored. Method at xxx:y used. -%warnfilter(509, 516) Pop::hip; // Overloaded xxxx is shadowed by xxxx at xxx:y. | Overloaded method xxxx ignored. Method at xxx:y used. -%warnfilter(509, 516) Pop::hop; // Overloaded xxxx is shadowed by xxxx at xxx:y. | Overloaded method xxxx ignored. Method at xxx:y used. -%warnfilter(509, 516) Pop::pop; // Overloaded xxxx is shadowed by xxxx at xxx:y. | Overloaded method xxxx ignored. Method at xxx:y used. -%warnfilter(516) Pop::bop; // Overloaded method xxxx ignored. Method at xxx:y used. -%warnfilter(516) Pop::bip; // Overloaded method xxxx ignored. Method at xxx:y used. -%warnfilter(509, 516) ::muzak; // Overloaded xxxx is shadowed by xxxx at xxx:y. | Overloaded method xxxx ignored. Method at xxx:y used. +// Different overloaded warning filters needed for scripting languages (eg Python) and for statically typed languages (eg C#). +%warnfilter(509, 516) Pop::Pop; +%warnfilter(509, 516) Pop::hip; +%warnfilter(509, 516) Pop::hop; +%warnfilter(509, 516) Pop::pop; +%warnfilter(516) Pop::bop; +%warnfilter(516) Pop::bip; +%warnfilter(509, 516) ::muzak; +%warnfilter(509, 516) foo; %typemap(in, numinputs=0) int l { $1 = 4711; } %inline %{ -double foo(int, int, char *, int) { +int foo(int, int, char *, int) { return 15; } -double foo(int i, int j, double k = 17.4, int l = 18, char m = 'P') { - return i + j + k + l + (int) m; +int foo(int i, int j, double k = 17.4, int l = 18 /* Note numinputs typemap above */, char m = 'P') { + int sum = i + j + (int)k + l + (int)m; + return sum; } struct Pop { @@ -67,6 +67,3 @@ int muzak(int& i) { return 3003; } int muzak(const int* i) { return 3004; } %} - -#endif - diff --git a/Examples/test-suite/overload_copy.i b/Examples/test-suite/overload_copy.i index a685f76e2..238d011a6 100644 --- a/Examples/test-suite/overload_copy.i +++ b/Examples/test-suite/overload_copy.i @@ -1,7 +1,6 @@ // Tests copy constructor %module overload_copy -#ifndef SWIG_NO_OVERLOAD %inline %{ class Foo { @@ -11,6 +10,3 @@ public: }; %} - -#endif - diff --git a/Examples/test-suite/overload_method.i b/Examples/test-suite/overload_method.i index 8b44b8172..f282df6e2 100644 --- a/Examples/test-suite/overload_method.i +++ b/Examples/test-suite/overload_method.i @@ -1,6 +1,11 @@ /* This test confirms the fix to sourceforge bug #3478922 for R */ %module overload_method + +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %inline %{ class Base { diff --git a/Examples/test-suite/overload_null.i b/Examples/test-suite/overload_null.i new file mode 100644 index 000000000..d4879fdb5 --- /dev/null +++ b/Examples/test-suite/overload_null.i @@ -0,0 +1,52 @@ +%module overload_null + +%{ +struct F {}; +%} + +%inline %{ +struct X {}; +struct Y {}; +struct F; + +struct Overload { + int byval1(X x) { return 1; } + int byval1(Y* y) { return 2; } + + int byval2(Y* y) { return 3; } + int byval2(X x) { return 4; } + + int byref1(X& x) { return 5; } + int byref1(Y* y) { return 6; } + + int byref2(Y* y) { return 7; } + int byref2(X& x) { return 8; } + + int byconstref1(const X& x) { return 9; } + int byconstref1(Y* y) { return 10; } + + int byconstref2(Y* y) { return 11; } + int byconstref2(const X& x) { return 12; } + + // const pointer references + int byval1cpr(X x) { return 13; } + int byval1cpr(Y*const& y) { return 14; } + + int byval2cpr(Y*const& y) { return 15; } + int byval2cpr(X x) { return 16; } + + // forward class declaration + int byval1forwardptr(X x) { return 17; } + int byval1forwardptr(F* f) { return 18; } + + int byval2forwardptr(F* f) { return 19; } + int byval2forwardptr(X x) { return 20; } + + int byval1forwardref(X x) { return 21; } + int byval1forwardref(F& f) { return -21; } + + int byval2forwardref(F& f) { return -22; } + int byval2forwardref(X x) { return 22; } + +}; +%} diff --git a/Examples/test-suite/overload_simple.i b/Examples/test-suite/overload_simple.i index 6bedf6cef..ba1900b40 100644 --- a/Examples/test-suite/overload_simple.i +++ b/Examples/test-suite/overload_simple.i @@ -19,7 +19,10 @@ %rename(Foos) Foo; #endif -#ifndef SWIG_NO_OVERLOAD +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) type; +#endif + %immutable Spam::type; %inline %{ @@ -177,8 +180,6 @@ long long ll(long long ull) { return ull; } %malloc(void); %free(void); -#endif - %inline { class ClassA diff --git a/Examples/test-suite/perl5/README b/Examples/test-suite/perl5/README index 804dec8e8..f15c07849 100644 --- a/Examples/test-suite/perl5/README +++ b/Examples/test-suite/perl5/README @@ -6,7 +6,7 @@ Test::More Support == Test::More is a standard perl test harness tool. -Support was added for for using Test::More in 1.3.28. +Support was added for using Test::More in 1.3.28. If adding a new test to this suite, please use Test::More. There are a few legacy test cases which do not use Test::More and these ought to be converted: diff --git a/Examples/test-suite/perl5/director_classes_runme.pl b/Examples/test-suite/perl5/director_classes_runme.pl index a4fddeed9..5e72703e0 100644 --- a/Examples/test-suite/perl5/director_classes_runme.pl +++ b/Examples/test-suite/perl5/director_classes_runme.pl @@ -1,6 +1,6 @@ use strict; use warnings; -use Test::More tests => 29; +use Test::More tests => 32; BEGIN { use_ok 'director_classes' } require_ok 'director_classes'; @@ -10,6 +10,7 @@ require_ok 'director_classes'; sub Val { $_[1] } sub Ref { $_[1] } sub Ptr { $_[1] } + sub ConstPtrRef { $_[1] } sub FullyOverloaded { my $rv = shift->SUPER::FullyOverloaded(@_); $rv =~ s/Base/__PACKAGE__/sge; @@ -45,6 +46,7 @@ sub makeCalls { my($caller, $base) = @_; is($caller->ValCall($dh)->{val}, $dh->{val}, "$bname.Val"); is($caller->RefCall($dh)->{val}, $dh->{val}, "$bname.Ref"); is($caller->PtrCall($dh)->{val}, $dh->{val}, "$bname.Ptr"); + is($caller->ConstPtrRefCall($dh)->{val}, $dh->{val}, "$bname.ConstPtrRef"); is($caller->FullyOverloadedCall(1), "${bname}::FullyOverloaded(int)", "$bname.FullyOverloaded(int)"); diff --git a/Examples/test-suite/perl5/global_vars_runme.pl b/Examples/test-suite/perl5/global_vars_runme.pl index b645f7bac..6375aa7da 100644 --- a/Examples/test-suite/perl5/global_vars_runme.pl +++ b/Examples/test-suite/perl5/global_vars_runme.pl @@ -1,6 +1,6 @@ use strict; use warnings; -use Test::More tests => 4; +use Test::More tests => 6; BEGIN { use_ok('global_vars') } require_ok('global_vars'); @@ -9,3 +9,9 @@ isa_ok($an, 'global_vars::A'); $global_vars::ap = $an; is($global_vars::ap, $an, "global var assignment"); +# Regression test for https://sourceforge.net/p/swig/bugs/564/ - changing the +# value in C/C++ apparently wasn't reflected in Perl: +$global_vars::x = 17; +is($global_vars::x, 17, "global var assignment"); +global_vars::init(); +is($global_vars::x, 1234, "C++ global var change visible in Perl"); diff --git a/Examples/test-suite/perl5/overload_null_runme.pl b/Examples/test-suite/perl5/overload_null_runme.pl new file mode 100644 index 000000000..7cc5090de --- /dev/null +++ b/Examples/test-suite/perl5/overload_null_runme.pl @@ -0,0 +1,44 @@ +use strict; +use warnings; +use Test::More tests => 24; +BEGIN { use_ok('overload_null') } +require_ok('overload_null'); + +my $o = new overload_null::Overload(); +my $x = new overload_null::X(); + +is(1, $o->byval1($x)); +is(2, $o->byval1(undef)); + +is(3, $o->byval2(undef)); +is(4, $o->byval2($x)); + +is(5, $o->byref1($x)); +is(6, $o->byref1(undef)); + +is(7, $o->byref2(undef)); +is(8, $o->byref2($x)); + +is(9, $o->byconstref1($x)); +is(10, $o->byconstref1(undef)); + +is(11, $o->byconstref2(undef)); +is(12, $o->byconstref2($x)); + +# const pointer references +is(13, $o->byval1cpr($x)); +is(14, $o->byval1cpr(undef)); + +is(15, $o->byval2cpr(undef)); +is(16, $o->byval2cpr($x)); + +# forward class declaration +is(17, $o->byval1forwardptr($x)); +is(18, $o->byval1forwardptr(undef)); + +is(19, $o->byval2forwardptr(undef)); +is(20, $o->byval2forwardptr($x)); + +is(21, $o->byval1forwardref($x)); + +is(22, $o->byval2forwardref($x)); diff --git a/Examples/test-suite/perl5/run-perl-test.pl b/Examples/test-suite/perl5/run-perl-test.pl index 106bf002b..5ea4e5115 100644 --- a/Examples/test-suite/perl5/run-perl-test.pl +++ b/Examples/test-suite/perl5/run-perl-test.pl @@ -7,7 +7,7 @@ use strict; my $command = shift @ARGV; -my $output = `$^X $command 2>&1`; +my $output = `$^X -I. $command 2>&1`; die "SWIG Perl test failed: \n\n$output\n" if $?; diff --git a/Examples/test-suite/perl5/scilab_multivalue_runme.pl b/Examples/test-suite/perl5/scilab_multivalue_runme.pl new file mode 100644 index 000000000..8be8834f7 --- /dev/null +++ b/Examples/test-suite/perl5/scilab_multivalue_runme.pl @@ -0,0 +1,88 @@ +use strict; +use warnings; +use Test::More tests => 44; +BEGIN { use_ok('scilab_multivalue') } +require_ok('scilab_multivalue'); + +my($a, $b, $c, $d, $ret); + +# OUTPUT + +($a, $b) = scilab_multivalue::output2(); +is($a, 1, "[a, b] = output2(): a"); +is($b, 2, "[a, b] = output2(): b"); + +($ret, $a, $b) = scilab_multivalue::output2Ret(); +is($ret, 3, "[a, b] = output2Ret(): b"); +is($a, 1, "[a, b] = output2Ret(): a"); +is($b, 2, "[a, b] = output2Ret(): b"); + +($c, $d) = scilab_multivalue::output2Input2(1, 2); +is($c, 2, "[c, d] = output2Input2(1, 2): c"); +is($d, 4, "[c, d] = output2Input2(1, 2): d"); + +($ret, $c, $d) = scilab_multivalue::output2Input2Ret(1, 2); +is($ret, 6, "[ret, c, d] = output2Input2Ret(1, 2): ret"); +is($c, 2, "[ret, c, d] = output2Input2Ret(1, 2): c"); +is($d, 4, "[ret, c, d = output2Input2Ret(1, 2): d"); + +($ret, $a, $b, $c) = scilab_multivalue::output3Input1Ret(10); +is($ret, 10, "[ret, a, b, c] = output3Input1Ret(10): ret"); +is($a, 11, "[ret, a, b, c] = output3Input1Ret(10): a"); +is($b, 12, "[ret, a, b, c] = output3Input1Ret(10): b"); +is($c, 13, "[ret, a, b, c] = output3Input1Ret(10): c"); + +($ret, $a, $b, $c) = scilab_multivalue::output3Input3Ret(10, 20, 30); +is($ret, 66, "[ret, a, b, c] = output3Input1Ret(10, 20, 30): ret"); +is($a, 11, "[ret, a, b, c] = output3Input1Ret(10, 20, 30): a"); +is($b, 22, "[ret, a, b, c] = output3Input1Ret(10, 20, 30): b"); +is($c, 33, "[ret, a, b, c] = output3Input1Ret(10, 20, 30): c"); + + +# INOUT + +($a, $b) = scilab_multivalue::inout2(1, 2); +is($a, 2, "[a, b] = output2(1, 2): a"); +is($b, 4, "[a, b] = output2(1, 2): b"); + +($ret, $a, $b) = scilab_multivalue::inout2Ret(1, 2); +is($ret, 6, "[a, b] = inout2Ret(1, 2): b"); +is($a, 2, "[a, b] = inout2Ret(1, 2): a"); +is($b, 4, "[a, b] = inout2Ret(1, 2): b"); + +($c, $d) = scilab_multivalue::inout2Input2(1, 2, 1, 1); +is($c, 2, "[c, d] = inout2Input2(1, 2): c"); +is($d, 3, "[c, d] = inout2Input2(1, 2): d"); + +($ret, $c, $d) = scilab_multivalue::inout2Input2Ret(1, 2, 1, 1); +is($ret, 5, "[c, d] = inout2Input2Ret(1, 2): ret"); +is($c, 2, "[c, d] = inout2Input2Ret(1, 2): c"); +is($d, 3, "[c, d] = inout2Input2Ret(1, 4): d"); + +($ret, $a, $b, $c) = scilab_multivalue::inout3Input1Ret(10, 1, 2, 3); +is($ret, 10, "[ret, a, b, c] = output3Input1Ret(ret, 1, 2, 3): ret"); +is($a, 11, "[ret, a, b, c] = output3Input1Ret(ret, 1, 2, 3): a"); +is($b, 12, "[ret, a, b, c] = output3Input1Ret(ret, 1, 2, 3): b"); +is($c, 13, "[ret, a, b, c] = output3Input1Ret(ret, 1, 2, 3): c"); + +($ret, $a, $b, $c) = scilab_multivalue::inout3Input3Ret(10, 1, 20, 2, 30, 3); +is($ret, 66, "[ret, a, b, c] = output3Input1Ret(10, 20, 30): ret"); +is($a, 11, "[ret, a, b, c] = inout3Input1Ret(10, 1, 20, 2, 30, 3): a"); +is($b, 22, "[ret, a, b, c] = inout3Input1Ret(10, 1, 20, 2, 30, 3): b"); +is($c, 33, "[ret, a, b, c] = inout3Input1Ret(10, 1, 20, 2, 30, 3): c"); + + +# CLASS + +$a = scilab_multivalue::ClassA->new(); + +($ret, $c, $d) = $a->output2Input2Ret(1, 2); +is($ret, 6, "[ret, c, d] = ClassA_output2Input2Ret(a, 1, 2): ret"); +is($c, 2, "[c, d] = ClassA_output2Input2Ret(a, 1, 2): c"); +is($d, 4, "[c, d] = ClassA_output2Input2Ret(a, 1, 2): d"); + +($ret, $c, $d) = $a->inout2Input2Ret(1, 2, 1, 1); +is($ret, 5, "[ret, c, d] = ClassA_inout2Input2Ret(a, 1, 2): ret"); +is($c, 2, "[c, d] = ClassA_inout2Input2(a, 1, 2): c"); +is($d, 3, "[c, d] = ClassA_inout2Input2(a, 1, 2): d"); + diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index 811eade36..64f0d1f9d 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -11,8 +11,10 @@ top_builddir = @top_builddir@ CPP_TEST_CASES += \ callback \ + li_factory \ php_iterator \ php_namewarn_rename \ + php_pragma \ include $(srcdir)/../common.mk diff --git a/Examples/test-suite/php/abstract_inherit_ok_runme.php b/Examples/test-suite/php/abstract_inherit_ok_runme.php index c2d86499b..c2c343dac 100644 --- a/Examples/test-suite/php/abstract_inherit_ok_runme.php +++ b/Examples/test-suite/php/abstract_inherit_ok_runme.php @@ -3,7 +3,7 @@ require "tests.php"; require "abstract_inherit_ok.php"; -check::classes(array(Foo,Spam)); +check::classes(array('Foo','Spam')); $spam=new Spam(); check::equal(0,$spam->blah(),"spam object method"); diff --git a/Examples/test-suite/php/abstract_inherit_runme.php b/Examples/test-suite/php/abstract_inherit_runme.php index 3554e6fd8..514bbc3b0 100644 --- a/Examples/test-suite/php/abstract_inherit_runme.php +++ b/Examples/test-suite/php/abstract_inherit_runme.php @@ -3,7 +3,7 @@ require "tests.php"; require "abstract_inherit.php"; -check::classes(array(Foo,Bar,Spam,NRFilter_i,NRRCFilter_i,NRRCFilterpro_i,NRRCFilterpri_i)); +check::classes(array('Foo','Bar','Spam','NRFilter_i','NRRCFilter_i','NRRCFilterpro_i','NRRCFilterpri_i')); // This constructor attempt should fail as there isn't one //$spam=new Spam(); diff --git a/Examples/test-suite/php/add_link_runme.php b/Examples/test-suite/php/add_link_runme.php index 7523bd604..3e16fa1df 100644 --- a/Examples/test-suite/php/add_link_runme.php +++ b/Examples/test-suite/php/add_link_runme.php @@ -4,15 +4,15 @@ require "tests.php"; require "add_link.php"; // No new functions, except the flat functions -check::functions(array(new_foo,foo_blah)); +check::functions(array('new_foo','foo_blah')); -check::classes(array(Foo)); +check::classes(array('Foo')); $foo=new foo(); -check::is_a($foo,foo); +check::is_a($foo,'foo'); $foo_blah=$foo->blah(); -check::is_a($foo_blah,foo); +check::is_a($foo_blah,'foo'); //fails, can't be called as a class method, should allow and make it nil? //$class_foo_blah=foo::blah(); diff --git a/Examples/test-suite/php/argout_runme.php b/Examples/test-suite/php/argout_runme.php index 33fbd8129..8b66613fd 100644 --- a/Examples/test-suite/php/argout_runme.php +++ b/Examples/test-suite/php/argout_runme.php @@ -3,7 +3,7 @@ require "tests.php"; require "argout.php"; -check::functions(array(incp,incr,inctr,new_intp,copy_intp,delete_intp,intp_assign,intp_value,voidhandle,handle)); +check::functions(array('incp','incr','inctr','new_intp','copy_intp','delete_intp','intp_assign','intp_value','voidhandle','handle')); $ip=copy_intp(42); check::equal(42,incp($ip),"42==incp($ip)"); @@ -30,7 +30,7 @@ unset($handle); #$handledata=handle($handle); #check::equal($handledata,"Here it is","\$handledata != \"Here it is\""); -unset($handle); +$handle=NULL; voidhandle($handle); check::isnull($handle,'$handle not null'); diff --git a/Examples/test-suite/php/arrayptr_runme.php b/Examples/test-suite/php/arrayptr_runme.php index 3b9baed05..86b7f8628 100644 --- a/Examples/test-suite/php/arrayptr_runme.php +++ b/Examples/test-suite/php/arrayptr_runme.php @@ -4,7 +4,7 @@ require "tests.php"; require "arrayptr.php"; // No new functions -check::functions(array(foo)); +check::functions(array('foo')); // No new classes check::classes(array()); // now new vars diff --git a/Examples/test-suite/php/arrays_global_runme.php b/Examples/test-suite/php/arrays_global_runme.php index 12a7806c9..95a300775 100644 --- a/Examples/test-suite/php/arrays_global_runme.php +++ b/Examples/test-suite/php/arrays_global_runme.php @@ -3,17 +3,17 @@ require "tests.php"; require "arrays_global.php"; -check::functions(array(test_a,test_b,new_simplestruct,new_material)); -check::classes(array(arrays_global,SimpleStruct,Material)); -check::globals(array(array_c,array_sc,array_uc,array_s,array_us,array_i,array_ui,array_l,array_ul,array_ll,array_f,array_d,array_struct,array_structpointers,array_ipointers,array_enum,array_enumpointers,array_const_i,beginstring_fix44a,beginstring_fix44b,beginstring_fix44c,beginstring_fix44d,beginstring_fix44e,beginstring_fix44f,chitmat,hitmat_val,hitmat,simplestruct_double_field)); +check::functions(array('test_a','test_b','new_simplestruct','new_material')); +check::classes(array('arrays_global','SimpleStruct','Material')); +check::globals(array('array_c','array_sc','array_uc','array_s','array_us','array_i','array_ui','array_l','array_ul','array_ll','array_f','array_d','array_struct','array_structpointers','array_ipointers','array_enum','array_enumpointers','array_const_i','beginstring_fix44a','beginstring_fix44b','beginstring_fix44c','beginstring_fix44d','beginstring_fix44e','beginstring_fix44f','chitmat','hitmat_val','hitmat','simplestruct_double_field')); // The size of array_c is 2, but the last byte is \0, so we can only store a // single byte string in it. -check::set(array_c,"Z"); -check::equal("Z",check::get(array_c),"set array_c"); -check::set(array_c,"xy"); -check::equal("x",check::get(array_c),"set array_c"); -check::set(array_c,"h"); -check::equal("h",check::get(array_c),"set array_c"); +check::set("array_c","Z"); +check::equal("Z",check::get("array_c"),"set array_c"); +check::set("array_c","xy"); +check::equal("x",check::get("array_c"),"set array_c"); +check::set("array_c","h"); +check::equal("h",check::get("array_c"),"set array_c"); check::done(); ?> diff --git a/Examples/test-suite/php/arrays_global_twodim_runme.php b/Examples/test-suite/php/arrays_global_twodim_runme.php index 40ecf1719..d9f50a6de 100644 --- a/Examples/test-suite/php/arrays_global_twodim_runme.php +++ b/Examples/test-suite/php/arrays_global_twodim_runme.php @@ -3,14 +3,14 @@ require "tests.php"; require "arrays_global_twodim.php"; -check::functions(array(fn_taking_arrays,get_2d_array,new_simplestruct,new_material)); -check::classes(array(arrays_global_twodim,SimpleStruct,Material)); -check::globals(array(array_c,array_sc,array_uc,array_s,array_us,array_i,array_ui,array_l,array_ul,array_ll,array_f,array_d,array_struct,array_structpointers,array_ipointers,array_enum,array_enumpointers,array_const_i,chitmat,hitmat_val,hitmat,simplestruct_double_field)); +check::functions(array('fn_taking_arrays','get_2d_array','new_simplestruct','new_material')); +check::classes(array('arrays_global_twodim','SimpleStruct','Material')); +check::globals(array('array_c','array_sc','array_uc','array_s','array_us','array_i','array_ui','array_l','array_ul','array_ll','array_f','array_d','array_struct','array_structpointers','array_ipointers','array_enum','array_enumpointers','array_const_i','chitmat','hitmat_val','hitmat','simplestruct_double_field')); $a1=array(10,11,12,13); $a2=array(14,15,16,17); $a=array($a1,$a2); -$_a=check::get(array_const_i); +$_a=check::get('array_const_i'); for($x=0;$xarray_c="abc"; diff --git a/Examples/test-suite/php/arrays_scope_runme.php b/Examples/test-suite/php/arrays_scope_runme.php index c208b7518..11c180870 100644 --- a/Examples/test-suite/php/arrays_scope_runme.php +++ b/Examples/test-suite/php/arrays_scope_runme.php @@ -4,11 +4,11 @@ require "tests.php"; require "arrays_scope.php"; // New functions -check::functions(array(new_bar,bar_blah)); +check::functions(array('new_bar','bar_blah')); // New classes -check::classes(array(arrays_scope,Bar)); +check::classes(array('arrays_scope','Bar')); // New vars -check::globals(array(bar_adata,bar_bdata,bar_cdata)); +check::globals(array('bar_adata','bar_bdata','bar_cdata')); $bar=new bar(); diff --git a/Examples/test-suite/php/casts_runme.php b/Examples/test-suite/php/casts_runme.php index 10522dca4..a9623a328 100644 --- a/Examples/test-suite/php/casts_runme.php +++ b/Examples/test-suite/php/casts_runme.php @@ -4,13 +4,13 @@ require "tests.php"; require "casts.php"; // No new functions -check::functions(array(new_a,a_hello,new_b)); +check::functions(array('new_a','a_hello','new_b')); // No new classes -check::classes(array(A,B)); +check::classes(array('A','B')); // now new vars check::globals(array()); -# Make sure $b inherites hello() from class A +# Make sure $b inherits hello() from class A $b=new B(); $b->hello(); diff --git a/Examples/test-suite/php/class_ignore_runme.php b/Examples/test-suite/php/class_ignore_runme.php index d5ce36217..ae4881f27 100644 --- a/Examples/test-suite/php/class_ignore_runme.php +++ b/Examples/test-suite/php/class_ignore_runme.php @@ -3,8 +3,8 @@ require "tests.php"; require "class_ignore.php"; -check::functions(array(do_blah,new_bar,bar_blah,new_boo,boo_away,new_far,new_hoo)); -check::classes(array(class_ignore,Bar,Boo,Far,Hoo)); +check::functions(array('do_blah','new_bar','bar_blah','new_boo','boo_away','new_far','new_hoo')); +check::classes(array('class_ignore','Bar','Boo','Far','Hoo')); // No new vars check::globals(array()); diff --git a/Examples/test-suite/php/cpp_basic_runme.php b/Examples/test-suite/php/cpp_basic_runme.php index 6a8522e3e..b24cf7000 100644 --- a/Examples/test-suite/php/cpp_basic_runme.php +++ b/Examples/test-suite/php/cpp_basic_runme.php @@ -4,11 +4,11 @@ require "tests.php"; require "cpp_basic.php"; // New functions -check::functions(array(foo_func1,foo_func2,foo___str__,foosubsub___str__,bar_test,bar_testfoo,get_func1_ptr,get_func2_ptr,test_func_ptr,fl_window_show)); +check::functions(array('foo_func1','foo_func2','foo___str__','foosubsub___str__','bar_test','bar_testfoo','get_func1_ptr','get_func2_ptr','test_func_ptr','fl_window_show')); // New classes -check::classes(array(cpp_basic,Foo,FooSub,FooSubSub,Bar,Fl_Window)); +check::classes(array('cpp_basic','Foo','FooSub','FooSubSub','Bar','Fl_Window')); // New vars -check::globals(array(foo_num,foo_func_ptr,bar_fptr,bar_fref,bar_fval,bar_cint,bar_global_fptr,bar_global_fref,bar_global_fval)); +check::globals(array('foo_num','foo_func_ptr','bar_fptr','bar_fref','bar_fval','bar_cint','bar_global_fptr','bar_global_fref','bar_global_fval')); $f = new Foo(3); $f->func_ptr = get_func1_ptr(); diff --git a/Examples/test-suite/php/cpp_static_runme.php b/Examples/test-suite/php/cpp_static_runme.php index e1cc3e733..20b50dd9e 100644 --- a/Examples/test-suite/php/cpp_static_runme.php +++ b/Examples/test-suite/php/cpp_static_runme.php @@ -4,11 +4,11 @@ require "tests.php"; require "cpp_static.php"; // New functions -check::functions(array(staticfunctiontest_static_func,staticfunctiontest_static_func_2,staticfunctiontest_static_func_3)); +check::functions(array('staticfunctiontest_static_func','staticfunctiontest_static_func_2','staticfunctiontest_static_func_3','is_python_builtin','staticmembertest_grab_int','staticbase_grab_statty_base','staticderived_grab_statty_derived')); // New classes -check::classes(array(StaticMemberTest,StaticFunctionTest)); +check::classes(array('StaticMemberTest','StaticFunctionTest','cpp_static','StaticBase','StaticDerived')); // New vars -check::globals(array(staticmembertest_static_int)); +check::globals(array('staticmembertest_static_int','staticbase_statty','staticderived_statty')); check::done(); ?> diff --git a/Examples/test-suite/php/director_abstract_runme.php b/Examples/test-suite/php/director_abstract_runme.php index ca3d676da..1a119cfd5 100644 --- a/Examples/test-suite/php/director_abstract_runme.php +++ b/Examples/test-suite/php/director_abstract_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "director_abstract.php"; // No new functions -check::functions(array(foo_ping,foo_pong,example0_getxsize,example0_color,example0_get_color,example1_getxsize,example1_color,example1_get_color,example2_getxsize,example2_color,example2_get_color,example4_getxsize,example4_color,example4_get_color,example3_i_color,example3_i_get_color,g,a_f)); +check::functions(array('foo_ping','foo_pong','example0_getxsize','example0_color','example0_get_color','example1_getxsize','example1_color','example1_get_color','example2_getxsize','example2_color','example2_get_color','example4_getxsize','example4_color','example4_get_color','example3_i_color','example3_i_get_color','g','a_f')); // No new classes -check::classes(array(director_abstract,Foo,Example0,Example1,Example2,Example4,Example3_i,A)); +check::classes(array('director_abstract','Foo','Example0','Example1','Example2','Example4','Example3_i','A')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/director_basic_runme.php b/Examples/test-suite/php/director_basic_runme.php index de6b50502..478a36f80 100644 --- a/Examples/test-suite/php/director_basic_runme.php +++ b/Examples/test-suite/php/director_basic_runme.php @@ -4,11 +4,11 @@ require "tests.php"; require "director_basic.php"; // No new functions -check::functions(array(foo_ping,foo_pong,foo_get_self,a_f,a_rg,a1_ff,myclass_method,myclass_vmethod,myclass_pmethod,myclass_cmethod,myclass_get_self,myclass_call_pmethod,myclasst_i_method)); +check::functions(array('foo_ping','foo_pong','foo_get_self','a_f','a_rg','a1_ff','myclass_method','myclass_vmethod','myclass_pmethod','myclass_cmethod','myclass_get_self','myclass_call_pmethod','myclasst_i_method','myclass_nonvirtual','myclass_nonoverride','myclass_call_nonvirtual','myclass_call_nonoverride','myclass_connect')); // No new classes -check::classes(array(Foo,A,A1,Bar,MyClass,MyClassT_i)); +check::classes(array('Foo','A','A1','Bar','MyClass','MyClassT_i')); // now new vars -check::globals(array(bar_x)); +check::globals(array('bar_x')); class PhpFoo extends Foo { function ping() { diff --git a/Examples/test-suite/php/director_classic_runme.php b/Examples/test-suite/php/director_classic_runme.php index d2da1b1ba..a44881e04 100644 --- a/Examples/test-suite/php/director_classic_runme.php +++ b/Examples/test-suite/php/director_classic_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "director_classic.php"; // No new functions -check::functions(array(being_id,person_id,child_id,grandchild_id,caller_delcallback,caller_setcallback,caller_resetcallback,caller_call,caller_baseclass)); +check::functions(array('being_id','person_id','child_id','grandchild_id','caller_delcallback','caller_setcallback','caller_resetcallback','caller_call','caller_baseclass')); // No new classes -check::classes(array(Being,Person,Child,GrandChild,OrphanPerson,OrphanChild,Caller)); +check::classes(array('Being','Person','Child','GrandChild','OrphanPerson','OrphanChild','Caller')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/director_default_runme.php b/Examples/test-suite/php/director_default_runme.php index f97fc7425..c459ce3ec 100644 --- a/Examples/test-suite/php/director_default_runme.php +++ b/Examples/test-suite/php/director_default_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "director_default.php"; // No new functions -check::functions(array(foo_msg,foo_getmsg,bar_msg,bar_getmsg,defaultsbase_defaultargs,defaultsderived_defaultargs)); +check::functions(array('foo_msg','foo_getmsg','bar_msg','bar_getmsg','defaultsbase_defaultargs','defaultsderived_defaultargs')); // No new classes -check::classes(array(Foo,Bar,DefaultsBase,DefaultsDerived)); +check::classes(array('Foo','Bar','DefaultsBase','DefaultsDerived')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/director_detect_runme.php b/Examples/test-suite/php/director_detect_runme.php index cc19c0302..a6d3aebd6 100644 --- a/Examples/test-suite/php/director_detect_runme.php +++ b/Examples/test-suite/php/director_detect_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "director_detect.php"; // No new functions -check::functions(array(foo_cloner,foo_get_value,foo_get_class,foo_just_do_it,bar_baseclass,bar_cloner,bar_get_value,bar_get_class,bar_just_do_it)); +check::functions(array('foo_cloner','foo_get_value','foo_get_class','foo_just_do_it','bar_baseclass','bar_cloner','bar_get_value','bar_get_class','bar_just_do_it')); // No new classes -check::classes(array(A,Foo,Bar)); +check::classes(array('A','Foo','Bar')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/director_enum_runme.php b/Examples/test-suite/php/director_enum_runme.php index 8f6487a28..0571ec0da 100644 --- a/Examples/test-suite/php/director_enum_runme.php +++ b/Examples/test-suite/php/director_enum_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "director_enum.php"; // No new functions -check::functions(array(foo_say_hello,foo_say_hi,foo_say_bye,foo_say_hi_ref,foo_ping,foo_ping_ref,foo_ping_member_enum,a_f,a2_f)); +check::functions(array('foo_say_hello','foo_say_hi','foo_say_bye','foo_say_hi_ref','foo_ping','foo_ping_ref','foo_ping_member_enum','a_f','a2_f')); // No new classes -check::classes(array(director_enum,Foo,A,B,A2,B2)); +check::classes(array('director_enum','Foo','A','B','A2','B2')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/director_exception_runme.php b/Examples/test-suite/php/director_exception_runme.php index 8b852c2ce..dd2d04e8a 100644 --- a/Examples/test-suite/php/director_exception_runme.php +++ b/Examples/test-suite/php/director_exception_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "director_exception.php"; // No new functions -check::functions(array(foo_ping,foo_pong,launder,bar_ping,bar_pong,bar_pang,returnalltypes_return_int,returnalltypes_return_double,returnalltypes_return_const_char_star,returnalltypes_return_std_string,returnalltypes_return_bar,returnalltypes_call_int,returnalltypes_call_double,returnalltypes_call_const_char_star,returnalltypes_call_std_string,returnalltypes_call_bar,is_python_builtin)); +check::functions(array('foo_ping','foo_pong','launder','bar_ping','bar_pong','returnalltypes_return_int','returnalltypes_return_double','returnalltypes_return_const_char_star','returnalltypes_return_std_string','returnalltypes_return_bar','returnalltypes_call_int','returnalltypes_call_double','returnalltypes_call_const_char_star','returnalltypes_call_std_string','returnalltypes_call_bar','is_python_builtin')); // No new classes -check::classes(array(director_exception,Foo,Exception1,Exception2,Base,Bar,ReturnAllTypes)); +check::classes(array('director_exception','Foo','Exception1','Exception2','Base','Bar','ReturnAllTypes')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/director_extend_runme.php b/Examples/test-suite/php/director_extend_runme.php index f283aefbe..7aa2e0f78 100644 --- a/Examples/test-suite/php/director_extend_runme.php +++ b/Examples/test-suite/php/director_extend_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "director_extend.php"; // No new functions -check::functions(array(spobject_getfoobar,spobject_dummy,spobject_exceptionmethod)); +check::functions(array('spobject_getfoobar','spobject_dummy','spobject_exceptionmethod')); // No new classes -check::classes(array(SpObject)); +check::classes(array('SpObject')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/director_finalizer_runme.php b/Examples/test-suite/php/director_finalizer_runme.php index 0fcddfd8b..96bb5c179 100644 --- a/Examples/test-suite/php/director_finalizer_runme.php +++ b/Examples/test-suite/php/director_finalizer_runme.php @@ -4,16 +4,16 @@ require "tests.php"; require "director_finalizer.php"; // No new functions -check::functions(array(foo_orstatus,deletefoo,getstatus,launder,resetstatus)); +check::functions(array('foo_orstatus','deletefoo','getstatus','launder','resetstatus')); // No new classes -check::classes(array(director_finalizer,Foo)); +check::classes(array('director_finalizer','Foo')); // now new vars check::globals(array()); class MyFoo extends Foo { function __destruct() { $this->orStatus(2); - if (method_exists(parent, "__destruct")) { + if (method_exists(get_parent_class(), "__destruct")) { parent::__destruct(); } } diff --git a/Examples/test-suite/php/director_frob_runme.php b/Examples/test-suite/php/director_frob_runme.php index 548b0b804..450a1234b 100644 --- a/Examples/test-suite/php/director_frob_runme.php +++ b/Examples/test-suite/php/director_frob_runme.php @@ -4,11 +4,11 @@ require "tests.php"; require "director_frob.php"; // No new functions -check::functions(array(alpha_abs_method,bravo_abs_method,charlie_abs_method,ops_opint,ops_opintstarstarconst,ops_opintamp,ops_opintstar,ops_opconstintintstar,prims_ull,prims_callull,corecallbacks_on3dengineredrawn,corecallbacks_on3dengineredrawn2)); +check::functions(array('alpha_abs_method','bravo_abs_method','charlie_abs_method','ops_opint','ops_opintstarstarconst','ops_opintamp','ops_opintstar','ops_opconstintintstar','prims_ull','prims_callull','corecallbacks_on3dengineredrawn','corecallbacks_on3dengineredrawn2')); // No new classes -check::classes(array(Alpha,Bravo,Charlie,Delta,Ops,Prims,corePoint3d,coreCallbacks_On3dEngineRedrawnData,coreCallbacksOn3dEngineRedrawnData,coreCallbacks)); +check::classes(array('Alpha','Bravo','Charlie','Delta','Ops','Prims','corePoint3d','coreCallbacks_On3dEngineRedrawnData','coreCallbacksOn3dEngineRedrawnData','coreCallbacks')); // now new vars -check::globals(array(corecallbacks_on3dengineredrawndata__eye,corecallbacks_on3dengineredrawndata__at,corecallbackson3dengineredrawndata__eye,corecallbackson3dengineredrawndata__at)); +check::globals(array('corecallbacks_on3dengineredrawndata__eye','corecallbacks_on3dengineredrawndata__at','corecallbackson3dengineredrawndata__eye','corecallbackson3dengineredrawndata__at')); $foo = new Bravo(); $s = $foo->abs_method(); diff --git a/Examples/test-suite/php/director_nested_runme.php b/Examples/test-suite/php/director_nested_runme.php index 4965e94f7..9a094a182 100644 --- a/Examples/test-suite/php/director_nested_runme.php +++ b/Examples/test-suite/php/director_nested_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "director_nested.php"; // No new functions -check::functions(array(foo_int_advance,foo_int_do_advance,bar_step,bar_do_advance,bar_do_step,foobar_int_get_value,foobar_int_get_name,foobar_int_name,foobar_int_get_self,foobar_int_do_advance,foobar_int_do_step)); +check::functions(array('foo_int_advance','foo_int_do_advance','bar_step','bar_do_advance','bar_do_step','foobar_int_get_value','foobar_int_get_name','foobar_int_name','foobar_int_get_self','foobar_int_do_advance','foobar_int_do_step')); // No new classes -check::classes(array(Foo_int,Bar,FooBar_int)); +check::classes(array('Foo_int','Bar','FooBar_int')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/director_profile_runme.php b/Examples/test-suite/php/director_profile_runme.php index c72421341..c6f4c3c94 100644 --- a/Examples/test-suite/php/director_profile_runme.php +++ b/Examples/test-suite/php/director_profile_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "director_profile.php"; // No new functions -check::functions(array(b_fn,b_vfi,b_fi,b_fj,b_fk,b_fl,b_get_self,b_vfs,b_fs)); +check::functions(array('b_fn','b_vfi','b_fi','b_fj','b_fk','b_fl','b_get_self','b_vfs','b_fs')); // No new classes -check::classes(array(A,B)); +check::classes(array('A','B')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/director_protected_runme.php b/Examples/test-suite/php/director_protected_runme.php index 18586ca62..e759fed25 100644 --- a/Examples/test-suite/php/director_protected_runme.php +++ b/Examples/test-suite/php/director_protected_runme.php @@ -3,9 +3,9 @@ require "tests.php"; require "director_protected.php"; -check::functions(array(foo_pong,foo_s,foo_q,foo_ping,foo_pang,foo_used,foo_cheer,bar_create,bar_callping,bar_callcheer,bar_cheer,bar_pong,bar_used,bar_ping,bar_pang,a_draw,b_draw)); -check::classes(array(Foo,Bar,PrivateFoo,A,B,AA,BB)); -check::globals(array(bar_a)); +check::functions(array('foo_pong','foo_s','foo_q','foo_ping','foo_pang','foo_used','foo_cheer','bar_create','bar_callping','bar_callcheer','bar_cheer','bar_pong','bar_used','bar_ping','bar_pang','a_draw','b_draw')); +check::classes(array('Foo','Bar','PrivateFoo','A','B','AA','BB')); +check::globals(array('bar_a')); class FooBar extends Bar { protected function ping() { diff --git a/Examples/test-suite/php/director_stl_runme.php b/Examples/test-suite/php/director_stl_runme.php index 29addd261..f7a5c0aa0 100644 --- a/Examples/test-suite/php/director_stl_runme.php +++ b/Examples/test-suite/php/director_stl_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "director_stl.php"; // No new functions -check::functions(array(foo_bar,foo_ping,foo_pong,foo_tping,foo_tpong,foo_pident,foo_vident,foo_vsecond,foo_tpident,foo_tvident,foo_tvsecond,foo_vidents,foo_tvidents)); +check::functions(array('foo_bar','foo_ping','foo_pong','foo_tping','foo_tpong','foo_pident','foo_vident','foo_vsecond','foo_tpident','foo_tvident','foo_tvsecond','foo_vidents','foo_tvidents')); // No new classes -check::classes(array(Foo)); +check::classes(array('Foo')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/director_string_runme.php b/Examples/test-suite/php/director_string_runme.php index 5ac583f78..77e84c9bf 100644 --- a/Examples/test-suite/php/director_string_runme.php +++ b/Examples/test-suite/php/director_string_runme.php @@ -4,11 +4,11 @@ require "tests.php"; require "director_string.php"; // No new functions -check::functions(array(a_get_first,a_call_get_first,a_string_length,a_process_text,a_call_process_func,stringvector_size,stringvector_is_empty,stringvector_clear,stringvector_push,stringvector_pop,stringvector_capacity,stringvector_reserve)); +check::functions(array('a_get_first','a_call_get_first','a_string_length','a_process_text','a_call_process_func','stringvector_size','stringvector_is_empty','stringvector_clear','stringvector_push','stringvector_pop','stringvector_capacity','stringvector_reserve')); // No new classes -check::classes(array(A,StringVector)); +check::classes(array('A','StringVector')); // now new vars -check::globals(array(a,a_call,a_m_strings,stringvector)); +check::globals(array('a','a_call','a_m_strings','stringvector')); class B extends A { function get_first() { diff --git a/Examples/test-suite/php/director_thread_runme.php b/Examples/test-suite/php/director_thread_runme.php index 809dec3e2..2a640a022 100644 --- a/Examples/test-suite/php/director_thread_runme.php +++ b/Examples/test-suite/php/director_thread_runme.php @@ -3,15 +3,16 @@ require "tests.php"; require "director_thread.php"; -# Fails in a ZTS-build of PHP - see: https://github.com/swig/swig/pull/155 +# Fails in a ZTS-build of PHP5 - see: https://github.com/swig/swig/pull/155 +# FIXME: Does this still fail in a threaded build of PHP7? exit(0); // No new functions -check::functions(array(millisecondsleep,foo_stop,foo_run,foo_do_foo)); +check::functions(array('millisecondsleep','foo_stop','foo_run','foo_do_foo')); // No new classes -check::classes(array(director_thread,Foo)); +check::classes(array('director_thread','Foo')); // now new vars -check::globals(array(foo_val)); +check::globals(array('foo_val')); class Derived extends Foo { function do_foo() { diff --git a/Examples/test-suite/php/director_unroll_runme.php b/Examples/test-suite/php/director_unroll_runme.php index 626b1f07d..e3101887d 100644 --- a/Examples/test-suite/php/director_unroll_runme.php +++ b/Examples/test-suite/php/director_unroll_runme.php @@ -4,11 +4,11 @@ require "tests.php"; require "director_unroll.php"; // No new functions -check::functions(array(foo_ping,foo_pong)); +check::functions(array('foo_ping','foo_pong')); // No new classes -check::classes(array(Foo,Bar)); +check::classes(array('Foo','Bar')); // now new vars -check::globals(array(bar)); +check::globals(array('bar')); class MyFoo extends Foo { function ping() { @@ -23,7 +23,10 @@ $b = new Bar(); $b->set($a); $c = $b->get(); -check::equal($a->this, $c->this, "this failed"); +// FIXME: This doesn't work for checking that they wrap the same C++ object +// because the two objects have different PHP resources, and we can't easily +// look inside those resources to see which C++ objects they refer to. +//check::equal($a->_cPtr, $c->_cPtr, "_cPtr check failed"); check::done(); ?> diff --git a/Examples/test-suite/php/evil_diamond_prop_runme.php b/Examples/test-suite/php/evil_diamond_prop_runme.php index 02d9944d6..9bdb7435f 100644 --- a/Examples/test-suite/php/evil_diamond_prop_runme.php +++ b/Examples/test-suite/php/evil_diamond_prop_runme.php @@ -31,7 +31,9 @@ check::is_a($spam,"spam"); check::equal(1,$spam->_foo,"1==spam->_foo"); check::equal(2,$spam->_bar,"2==spam->_bar"); // multiple inheritance not supported in PHP +set_error_handler(NULL, 0); // Don't complain that _baz is unknown. check::equal(null,$spam->_baz,"null==spam->_baz"); +restore_error_handler(); check::equal(4,$spam->_spam,"4==spam->_spam"); check::done(); diff --git a/Examples/test-suite/php/exception_order_runme.php b/Examples/test-suite/php/exception_order_runme.php index acb83561a..77f115fa1 100644 --- a/Examples/test-suite/php/exception_order_runme.php +++ b/Examples/test-suite/php/exception_order_runme.php @@ -2,9 +2,9 @@ require "tests.php"; require "exception_order.php"; -check::functions(array(a_foo,a_bar,a_foobar,a_barfoo,is_python_builtin)); -check::classes(array(A,E1,E2,E3,exception_order,ET_i,ET_d)); -check::globals(array(efoovar,foovar,cfoovar,a_sfoovar,a_foovar,a_efoovar)); +check::functions(array('a_foo','a_bar','a_foobar','a_barfoo','is_python_builtin')); +check::classes(array('A','E1','E2','E3','exception_order','ET_i','ET_d')); +check::globals(array('efoovar','foovar','cfoovar','a_sfoovar','a_foovar','a_efoovar')); $a = new A(); try { diff --git a/Examples/test-suite/php/grouping_runme.php b/Examples/test-suite/php/grouping_runme.php index 51446f473..8bad7cd4c 100644 --- a/Examples/test-suite/php/grouping_runme.php +++ b/Examples/test-suite/php/grouping_runme.php @@ -6,14 +6,14 @@ require "grouping.php"; check::functions(array("test1","test2","do_unary","negate")); check::equal(5,test1(5),"5==test1(5)"); check::resource(test2(7),"_p_int","_p_int==test2(7)"); -check::globals(array(test3)); +check::globals(array('test3')); //check::equal(37,test3_get(),'37==test3_get()'); check::equal(37,check::get("test3"),'37==get(test3)'); //test3_set(38); -check::set(test3,38); +check::set('test3',38); //check::equal(38,test3_get(),'38==test3_get() after test3_set(37)'); -check::equal(38,check::get(test3),'38==get(test3) after set(test)'); +check::equal(38,check::get('test3'),'38==get(test3) after set(test)'); check::equal(-5,negate(5),"-5==negate(5)"); check::equal(7,do_unary(-7,NEGATE),"7=do_unary(-7,NEGATE)"); diff --git a/Examples/test-suite/php/ignore_parameter_runme.php b/Examples/test-suite/php/ignore_parameter_runme.php index 1c8c76ad4..b9c2b777d 100644 --- a/Examples/test-suite/php/ignore_parameter_runme.php +++ b/Examples/test-suite/php/ignore_parameter_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "ignore_parameter.php"; // New functions -check::functions(array(jaguar,lotus,tvr,ferrari,sportscars_daimler,sportscars_astonmartin,sportscars_bugatti,sportscars_lamborghini)); +check::functions(array('jaguar','lotus','tvr','ferrari','fiat','sportscars_daimler','sportscars_astonmartin','sportscars_bugatti','sportscars_lamborghini','sportscars_maseratti')); // New classes -check::classes(array(ignore_parameter,SportsCars,MiniCooper,MorrisMinor,FordAnglia,AustinAllegro)); +check::classes(array('ignore_parameter','SportsCars','MiniCooper','MorrisMinor','FordAnglia','AustinAllegro')); // No new vars check::globals(array()); diff --git a/Examples/test-suite/php/import_nomodule_runme.php b/Examples/test-suite/php/import_nomodule_runme.php index 41836ba0f..e5ea761f7 100644 --- a/Examples/test-suite/php/import_nomodule_runme.php +++ b/Examples/test-suite/php/import_nomodule_runme.php @@ -3,9 +3,9 @@ require "tests.php"; require "import_nomodule.php"; // No new functions -check::functions(array(create_foo,delete_foo,test1,is_python_builtin)); +check::functions(array('create_foo','delete_foo','test1','is_python_builtin')); // No new classes -check::classes(array(import_nomodule,Bar)); +check::classes(array('import_nomodule','Bar')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/li_carrays_cpp_runme.php b/Examples/test-suite/php/li_carrays_cpp_runme.php index 3be09ca8c..3e8a443f6 100644 --- a/Examples/test-suite/php/li_carrays_cpp_runme.php +++ b/Examples/test-suite/php/li_carrays_cpp_runme.php @@ -3,14 +3,14 @@ require "tests.php"; require "li_carrays_cpp.php"; // Check functions. -check::functions(array(new_intarray,delete_intarray,intarray_getitem,intarray_setitem,doublearray_getitem,doublearray_setitem,doublearray_cast,doublearray_frompointer,xyarray_getitem,xyarray_setitem,xyarray_cast,xyarray_frompointer,delete_abarray,abarray_getitem,abarray_setitem)); +check::functions(array('new_intarray','delete_intarray','intarray_getitem','intarray_setitem','doublearray_getitem','doublearray_setitem','doublearray_cast','doublearray_frompointer','xyarray_getitem','xyarray_setitem','xyarray_cast','xyarray_frompointer','delete_abarray','abarray_getitem','abarray_setitem','shortarray_getitem','shortarray_setitem','shortarray_cast','shortarray_frompointer','sum_array')); // Check classes. // NB An "li_carrays_cpp" class is created as a mock namespace. -check::classes(array(li_carrays_cpp,doubleArray,AB,XY,XYArray)); +check::classes(array('li_carrays_cpp','doubleArray','AB','XY','XYArray','shortArray')); // Check global variables. -check::globals(array(xy_x,xy_y,globalxyarray,ab_a,ab_b,globalabarray)); +check::globals(array('xy_x','xy_y','globalxyarray','ab_a','ab_b','globalabarray')); $d = new doubleArray(10); diff --git a/Examples/test-suite/php/li_carrays_runme.php b/Examples/test-suite/php/li_carrays_runme.php index fbe5cc793..abe358101 100644 --- a/Examples/test-suite/php/li_carrays_runme.php +++ b/Examples/test-suite/php/li_carrays_runme.php @@ -3,14 +3,14 @@ require "tests.php"; require "li_carrays.php"; // Check functions. -check::functions(array(new_intarray,delete_intarray,intarray_getitem,intarray_setitem,doublearray_getitem,doublearray_setitem,doublearray_cast,doublearray_frompointer,xyarray_getitem,xyarray_setitem,xyarray_cast,xyarray_frompointer,delete_abarray,abarray_getitem,abarray_setitem)); +check::functions(array('new_intarray','delete_intarray','intarray_getitem','intarray_setitem','doublearray_getitem','doublearray_setitem','doublearray_cast','doublearray_frompointer','xyarray_getitem','xyarray_setitem','xyarray_cast','xyarray_frompointer','delete_abarray','abarray_getitem','abarray_setitem','shortarray_getitem','shortarray_setitem','shortarray_cast','shortarray_frompointer','sum_array')); // Check classes. // NB An "li_carrays" class is created as a mock namespace. -check::classes(array(li_carrays,doubleArray,AB,XY,XYArray)); +check::classes(array('li_carrays','doubleArray','AB','XY','XYArray','shortArray')); // Check global variables. -check::globals(array(xy_x,xy_y,globalxyarray,ab_a,ab_b,globalabarray)); +check::globals(array('xy_x','xy_y','globalxyarray','ab_a','ab_b','globalabarray')); $d = new doubleArray(10); diff --git a/Examples/test-suite/php/li_factory_runme.php b/Examples/test-suite/php/li_factory_runme.php index 6623e2a8c..982d7b1fd 100644 --- a/Examples/test-suite/php/li_factory_runme.php +++ b/Examples/test-suite/php/li_factory_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "li_factory.php"; // No new functions -check::functions(array(geometry_draw,geometry_create,geometry_clone_,point_draw,point_width,point_clone_,circle_draw,circle_radius,circle_clone_)); +check::functions(array('geometry_draw','geometry_create','geometry_clone_','point_draw','point_width','point_clone_','circle_draw','circle_radius','circle_clone_')); // No new classes -check::classes(array(Geometry,Point,Circle)); +check::classes(array('Geometry','Point','Circle')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/li_std_string_runme.php b/Examples/test-suite/php/li_std_string_runme.php index ad62247e1..04ee3fc86 100644 --- a/Examples/test-suite/php/li_std_string_runme.php +++ b/Examples/test-suite/php/li_std_string_runme.php @@ -27,5 +27,8 @@ check::equal(Structure::StaticMemberString2(), $s, "StaticMemberString2 test 2") // below broken ? //check::equal(Structure::ConstStaticMemberString(), "const static member string", "ConstStaticMemberString test"); +// This used to give "Undefined variable: r" +li_std_string::test_const_reference_returning_void("foo"); + check::done(); ?> diff --git a/Examples/test-suite/php/newobject1_runme.php b/Examples/test-suite/php/newobject1_runme.php index 5853a72c0..863e3e423 100644 --- a/Examples/test-suite/php/newobject1_runme.php +++ b/Examples/test-suite/php/newobject1_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "newobject1.php"; // No new functions -check::functions(array(foo_makefoo,foo_makemore,foo_foocount)); +check::functions(array('foo_makefoo','foo_makemore','foo_foocount')); // No new classes -check::classes(array(Foo)); +check::classes(array('Foo')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/newobject3_runme.php b/Examples/test-suite/php/newobject3_runme.php new file mode 100644 index 000000000..edd5d8608 --- /dev/null +++ b/Examples/test-suite/php/newobject3_runme.php @@ -0,0 +1,18 @@ +create(7)); +check::classname("Product", $factory->create(7, 6)); +check::classname("Product", $factory->create("test")); +check::classname("Product", $factory->create("test", 2)); + +check::isnull($factory->create(0), "create(0) should be NULL"); +check::isnull($factory->create(7, -1), "create(7, -1) should be NULL"); +check::isnull($factory->create(0, -1), "create(0, -1) should be NULL"); +check::isnull($factory->create("bad", -1), "create(\"bad\", -1) should be NULL"); + +?> diff --git a/Examples/test-suite/php/overload_null_runme.php b/Examples/test-suite/php/overload_null_runme.php new file mode 100644 index 000000000..22824d4fb --- /dev/null +++ b/Examples/test-suite/php/overload_null_runme.php @@ -0,0 +1,46 @@ +byval1($x), "test 1"); +check::equal(2, $o->byval1(null), "test 2"); + +check::equal(3, $o->byval2(null), "test 3"); +check::equal(4, $o->byval2($x), "test 4"); + +check::equal(5, $o->byref1($x), "test 5"); +check::equal(6, $o->byref1(null), "test 6"); + +check::equal(7, $o->byref2(null), "test 7"); +check::equal(8, $o->byref2($x), "test 8"); + +check::equal(9, $o->byconstref1($x), "test 9"); +check::equal(10, $o->byconstref1(null), "test 10"); + +check::equal(11, $o->byconstref2(null), "test 11"); +check::equal(12, $o->byconstref2($x), "test 12"); + +# const pointer references +check::equal(13, $o->byval1cpr($x), "test 13"); +check::equal(14, $o->byval1cpr(null), "test 14"); + +check::equal(15, $o->byval2cpr(null), "test 15"); +check::equal(16, $o->byval2cpr($x), "test 16"); + +# forward class declaration +check::equal(17, $o->byval1forwardptr($x), "test 17"); +check::equal(18, $o->byval1forwardptr(null), "test 18"); + +check::equal(19, $o->byval2forwardptr(null), "test 19"); +check::equal(20, $o->byval2forwardptr($x), "test 20"); + +check::equal(21, $o->byval1forwardref($x), "test 21"); + +check::equal(22, $o->byval2forwardref($x), "test 22"); + +check::done(); +?> diff --git a/Examples/test-suite/php/overload_rename_runme.php b/Examples/test-suite/php/overload_rename_runme.php index dce4c6cb3..0357f91a6 100644 --- a/Examples/test-suite/php/overload_rename_runme.php +++ b/Examples/test-suite/php/overload_rename_runme.php @@ -6,7 +6,7 @@ require "overload_rename.php"; // No new functions check::functions(array()); // No new classes -check::classes(array(Foo)); +check::classes(array('Foo')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/php_iterator_runme.php b/Examples/test-suite/php/php_iterator_runme.php index d69a5b385..fd645ccb2 100644 --- a/Examples/test-suite/php/php_iterator_runme.php +++ b/Examples/test-suite/php/php_iterator_runme.php @@ -3,8 +3,8 @@ require "tests.php"; require "php_iterator.php"; -check::functions(array(myiterator_rewind,myiterator_key,myiterator_current,myiterator_next,myiterator_valid)); -check::classes(array(MyIterator)); +check::functions(array('myiterator_rewind','myiterator_key','myiterator_current','myiterator_next','myiterator_valid')); +check::classes(array('MyIterator')); // No new global variables. check::globals(array()); diff --git a/Examples/test-suite/php/php_pragma_runme.php b/Examples/test-suite/php/php_pragma_runme.php new file mode 100644 index 000000000..c76cfc9b5 --- /dev/null +++ b/Examples/test-suite/php/php_pragma_runme.php @@ -0,0 +1,11 @@ +getVersion(),"1.5==version(php_pragma)"); + +check::done(); + +?> diff --git a/Examples/test-suite/php/prefix_runme.php b/Examples/test-suite/php/prefix_runme.php index ead064f5b..fcf7c66f6 100644 --- a/Examples/test-suite/php/prefix_runme.php +++ b/Examples/test-suite/php/prefix_runme.php @@ -4,9 +4,9 @@ require "tests.php"; require "prefix.php"; // No new functions -check::functions(array(foo_get_self)); +check::functions(array('foo_get_self')); // No new classes -check::classes(array(ProjectFoo)); +check::classes(array('ProjectFoo')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/preproc_constants_c_runme.php b/Examples/test-suite/php/preproc_constants_c_runme.php new file mode 100644 index 000000000..20868dcc0 --- /dev/null +++ b/Examples/test-suite/php/preproc_constants_c_runme.php @@ -0,0 +1,69 @@ + diff --git a/Examples/test-suite/php/preproc_constants_runme.php b/Examples/test-suite/php/preproc_constants_runme.php new file mode 100644 index 000000000..bd216c269 --- /dev/null +++ b/Examples/test-suite/php/preproc_constants_runme.php @@ -0,0 +1,68 @@ + diff --git a/Examples/test-suite/php/swig_exception_runme.php b/Examples/test-suite/php/swig_exception_runme.php new file mode 100644 index 000000000..76641996e --- /dev/null +++ b/Examples/test-suite/php/swig_exception_runme.php @@ -0,0 +1,33 @@ +throwException(); + check::fail("Exception wasn't thrown"); +} catch (Exception $e) { + if ($e->getMessage() != "OK") { + check::fail("Exception getMessage() should be \"OK\", actually \"".$e->getMessage()."\""); + } +} + +# ----- Delete everything ----- + +$c = NULL; +$s = NULL; +$e = NULL; + +if (Shape::nshapes() != 0) { + check::fail("Shape::nshapes() should be 0, actually ".Shape::nshapes()); +} + +?> diff --git a/Examples/test-suite/php/sym_runme.php b/Examples/test-suite/php/sym_runme.php index 483aaa980..127d28fd9 100644 --- a/Examples/test-suite/php/sym_runme.php +++ b/Examples/test-suite/php/sym_runme.php @@ -6,7 +6,7 @@ require "sym.php"; // No new functions check::functions(array()); // No new classes -check::classes(array(flim,flam)); +check::classes(array('flim','flam')); // now new vars check::globals(array()); diff --git a/Examples/test-suite/php/template_arg_typename_runme.php b/Examples/test-suite/php/template_arg_typename_runme.php index 7d60285e3..e609240e7 100644 --- a/Examples/test-suite/php/template_arg_typename_runme.php +++ b/Examples/test-suite/php/template_arg_typename_runme.php @@ -6,11 +6,11 @@ require "template_arg_typename.php"; // No new functions check::functions(array()); // No new classes -check::classes(array(UnaryFunction_bool_bool,BoolUnaryFunction_bool)); +check::classes(array('UnaryFunction_bool_bool','BoolUnaryFunction_bool')); $ufbb=new unaryfunction_bool_bool(); check::is_a($ufbb,"unaryfunction_bool_bool"); -unset($whatisthis); +$whatisthis=NULL; $bufb=new boolunaryfunction_bool($whatisthis); check::is_a($bufb,"boolunaryfunction_bool"); diff --git a/Examples/test-suite/php/template_construct_runme.php b/Examples/test-suite/php/template_construct_runme.php index 3a3986f7e..b227d9fec 100644 --- a/Examples/test-suite/php/template_construct_runme.php +++ b/Examples/test-suite/php/template_construct_runme.php @@ -3,7 +3,7 @@ require "tests.php"; require "template_construct.php"; -check::classes(array(Foo_int)); +check::classes(array('Foo_int')); $foo_int=new foo_int(3); check::is_a($foo_int,"foo_int","Made a foo_int"); diff --git a/Examples/test-suite/php/tests.php b/Examples/test-suite/php/tests.php index d3fd66868..20fa1ed98 100644 --- a/Examples/test-suite/php/tests.php +++ b/Examples/test-suite/php/tests.php @@ -1,8 +1,15 @@ " +# 1 "" +# 1 "/usr/include/stdc-predef.h" 1 3 4 +# 1 "" 2 +# 1 "header1.h" +# 18 "header1.h" +void header1_function_a(int a); +# 1 "header2.h" 1 +# 13 "header2.h" +void header2_function(int x); +# 20 "header1.h" 2 +void header1_function_b(int b); diff --git a/Examples/test-suite/preproc_gcc_output.i b/Examples/test-suite/preproc_gcc_output.i new file mode 100644 index 000000000..b4db9e70a --- /dev/null +++ b/Examples/test-suite/preproc_gcc_output.i @@ -0,0 +1,12 @@ +%module preproc_gcc_output +// Testcase for Github issue #1475 using the output of gcc -E + +// The file below was generated using 'gcc -E header1.h' +// where header1.h included header2.h +%include "preproc_gcc_output.h" + +%{ +void header1_function_a(int a) {} +void header2_function(int x) {} +void header1_function_b(int b) {} +%} diff --git a/Examples/test-suite/primitive_types.i b/Examples/test-suite/primitive_types.i index b9b973a2b..a71f62a4f 100644 --- a/Examples/test-suite/primitive_types.i +++ b/Examples/test-suite/primitive_types.i @@ -7,12 +7,6 @@ %rename(TestDir) TestDirector; #endif -%{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif -%} - // Ruby constant names #pragma SWIG nowarn=SWIGWARN_RUBY_WRONG_NAME @@ -259,14 +253,17 @@ macro(Param, pfx, paramc) macro(size_t, pfx, sizet) %enddef +%define catches_decl(type, pfx, name) + %catches(type) pfx##_##name(type x); +%enddef /* function passing by value */ %define val_decl(type, pfx, name) - type pfx##_##name(type x) throw (type) { return x; } + type pfx##_##name(type x) { return x; } %enddef /* function passing by ref */ %define ref_decl(type, pfx, name) - const type& pfx##_##name(const type& x) throw (type) { return x; } + const type& pfx##_##name(const type& x) { return x; } %enddef /* C++ constant declaration */ @@ -301,6 +298,11 @@ macro(size_t, pfx, sizet) %test_prim_types(sct_decl, sct) +%test_prim_types(catches_decl, val) +%test_prim_types(catches_decl, ref) +%test_prim_types(catches_decl, cct) +%test_prim_types(catches_decl, var) + %inline { %test_prim_types(val_decl, val) %test_prim_types(ref_decl, ref) @@ -452,12 +454,12 @@ macro(size_t, pfx, sizet) var_decl(namet, var, namet) - const char* val_namet(namet x) throw(namet) + const char* val_namet(namet x) { return x; } - const char* val_cnamet(const namet x) throw(namet) + const char* val_cnamet(const namet x) { return x; } @@ -465,7 +467,7 @@ macro(size_t, pfx, sizet) #if 0 /* I have no idea how to define a typemap for const namet&, where namet is a char[ANY] array */ - const namet& ref_namet(const namet& x) throw(namet) + const namet& ref_namet(const namet& x) { return x; } @@ -509,12 +511,12 @@ macro(size_t, pfx, sizet) var_namet[0]='h'; } - virtual const char* vval_namet(namet x) throw(namet) + virtual const char* vval_namet(namet x) { return x; } - virtual const char* vval_cnamet(const namet x) throw(namet) + virtual const char* vval_cnamet(const namet x) { return x; } @@ -522,7 +524,7 @@ macro(size_t, pfx, sizet) #if 0 /* I have no idea how to define a typemap for const namet&, where namet is a char[ANY] array */ - virtual const namet& vref_namet(const namet& x) throw(namet) + virtual const namet& vref_namet(const namet& x) { return x; } @@ -559,7 +561,7 @@ macro(size_t, pfx, sizet) %test_prim_types_ovr(ovr_decl, ovr) - virtual Test* vtest(Test* t) const throw (Test) + virtual Test* vtest(Test* t) const { return t; } @@ -628,6 +630,10 @@ macro(size_t, pfx, sizet) float val_float(float x) { return x; } + + float val_float_3(float f = 0e1f, float f2 = 020e0f, float f3 = 0.3e4f) { + return f + f2 + f3; + } %} diff --git a/Examples/test-suite/proxycode.i b/Examples/test-suite/proxycode.i new file mode 100644 index 000000000..02dab9ade --- /dev/null +++ b/Examples/test-suite/proxycode.i @@ -0,0 +1,141 @@ +%module proxycode + +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Proxy4::Proxy4Nested; + +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) + +%{ +struct Proxy1 {}; +%} +struct Proxy1 { +%proxycode %{ + public int proxycode1(int i) { + return i+1; + } +%} +}; + +%proxycode %{ + this should be ignored as it is not in scope of a class +%} + +%extend Proxy2 { +%proxycode %{ + public int proxycode2a(int i) { + return i+2; + } +%} +} + +%extend Proxy2 { +%proxycode %{ + public int proxycode2b(int i) { + return i+2; + } +%} +} + +%inline %{ +struct Proxy2 {}; +struct Proxy3 {}; +struct Proxy4 { + struct Proxy4Nested {}; +}; +%} + +%extend Proxy3 { +%proxycode %{ + public int proxycode3(int i) { + return i+3; + } +%} +} + +%extend Proxy4 { +%proxycode %{ + public int proxycode4(int i) { + return i+4; + } +%} +} +%extend Proxy4::Proxy4Nested { +%proxycode %{ + public int proxycode4nested(int i) { + return i+44; + } +%} +} + +%extend TemplateProxy { +%proxycode %{ + public T proxycode5(T i) { + return i; + } +%} +} + +%extend TemplateProxy { +%proxycode %{ + public int proxycode5(int i, int j) { + return i+j+55; + } +%} +} + +%inline %{ +template struct TemplateProxy {}; +%} + +%template(Proxy5a) TemplateProxy; +%template(Proxy5b) TemplateProxy; + +%inline %{ +template struct TypemapProxy { + T useT(T t1, T const& t2) { + return t1+t2; + } +}; +%} + +%extend TypemapProxy { +#if defined(SWIGJAVA) +%proxycode %{ + public $javaclassname proxyUseT(long t1, long t2) { + $typemap(jstype, unsigned int) tt1 = t1; + $typemap(jstype, unsigned int const&) tt2 = t2; + long ret = useT(tt1, tt2); + if (ret != t1+t2) + throw new RuntimeException("wrong sum"); + return this; + } +%} +#elif defined(SWIGCSHARP) +%proxycode %{ + public $csclassname proxyUseT(uint t1, uint t2) { + $typemap(cstype, unsigned int) tt1 = t1; + $typemap(cstype, unsigned int const&) tt2 = t2; + uint ret = useT(tt1, tt2); + if (ret != t1+t2) + throw new System.Exception("wrong sum"); + return this; + } +%} +#elif defined(SWIGD) +%proxycode %{ + public $dclassname proxyUseT(uint t1, uint t2) { + $typemap(dtype, unsigned int) tt1 = t1; + $typemap(dtype, unsigned int const&) tt2 = t2; + uint ret = useT(tt1, tt2); + if (ret != t1+t2) + throw new Exception("wrong sum"); + return this; + } +%} +#else +#error "missing test" +#endif +} + +%template(Proxy6) TypemapProxy; + +#endif diff --git a/Examples/test-suite/pure_virtual.i b/Examples/test-suite/pure_virtual.i index 9e345e2a4..c1c7edc15 100644 --- a/Examples/test-suite/pure_virtual.i +++ b/Examples/test-suite/pure_virtual.i @@ -12,6 +12,10 @@ SWIGWARN_D_MULTIPLE_INHERITANCE, SWIGWARN_PHP_MULTIPLE_INHERITANCE) E; /* C#, D, Java, PHP multiple inheritance */ +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %nodefaultctor C; %nodefaultdtor C; %nodefaultctor E; diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index bfc5450b0..be06f7e51 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -10,13 +10,13 @@ endif LANGUAGE = python PYTHON = $(PYBIN) -PEP8 = @PEP8@ -PEP8_FLAGS = --ignore=E30,E402,E501,E731,W291,W391 +PYCODESTYLE = @PYCODESTYLE@ +PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,W291,W391 #*_runme.py for Python 2.x, *_runme3.py for Python 3.x PY2SCRIPTSUFFIX = _runme.py PY3SCRIPTSUFFIX = _runme3.py -PY2TO3 = 2to3 -x import +PY2TO3 = @PY2TO3@ -x import ifeq (,$(PY3)) SCRIPTSUFFIX = $(PY2SCRIPTSUFFIX) @@ -45,6 +45,7 @@ CPP_TEST_CASES += \ li_factory \ li_implicit \ li_std_containers_int \ + li_std_list \ li_std_map_member \ li_std_multimap \ li_std_pair_extra \ @@ -54,7 +55,7 @@ CPP_TEST_CASES += \ li_std_vectora \ li_std_vector_extra \ li_std_wstream \ - li_std_wstring \ + li_std_wstring_inherit \ primitive_types \ python_abstractbase \ python_append \ @@ -62,26 +63,40 @@ CPP_TEST_CASES += \ python_destructor_exception \ python_director \ python_docstring \ - python_nondynamic \ + python_extranative \ + python_moduleimport \ python_overload_simple_cast \ + python_pickle \ + python_pybuffer \ python_pythoncode \ python_richcompare \ python_strict_unicode \ + python_threads \ simutry \ std_containers \ swigobject \ - template_matrix + template_matrix \ # li_std_carray # director_profile -# python_pybuf + +CPP11_TEST_CASES = \ + cpp11_hash_tables \ + cpp11_shared_ptr_const \ + cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ + cpp11_shared_ptr_upcast \ + cpp11_std_unordered_map \ + cpp11_std_unordered_multimap \ + cpp11_std_unordered_multiset \ + cpp11_std_unordered_set \ C_TEST_CASES += \ file_test \ li_cstring \ li_cwstring \ python_nondynamic \ - python_varargs_typemap + python_varargs_typemap \ # # This test only works with modern C compilers @@ -130,12 +145,12 @@ py_runme = $(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) py2_runme = $(SCRIPTPREFIX)$*$(PY2SCRIPTSUFFIX) py3_runme = $(SCRIPTPREFIX)$*$(PY3SCRIPTSUFFIX) -ifneq (,$(PEP8)) -check_pep8 = $(COMPILETOOL) $(PEP8) $(PEP8_FLAGS) $(SCRIPTPREFIX)$*.py +ifneq (,$(PYCODESTYLE)) +check_pep8 = $(COMPILETOOL) $(PYCODESTYLE) $(PYCODESTYLE_FLAGS) $(SCRIPTPREFIX)$*.py check_pep8_multi_cpp = \ for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ - $(COMPILETOOL) $(PEP8) $(PEP8_FLAGS) $$f.py; \ + $(COMPILETOOL) $(PYCODESTYLE) $(PYCODESTYLE_FLAGS) $$f.py; \ done endif @@ -146,19 +161,54 @@ run_testcase = \ $(run_python);\ fi -# No copying/conversion needed for in-source-tree Python 2 scripts -ifeq ($(SCRIPTDIR)|$(SCRIPTSUFFIX),$(srcdir)|$(PY2SCRIPTSUFFIX)) -convert_testcase = -else - -convert_testcase = \ +# Grab runme file ready for running: copied for out of source tree builds, and/or run 2to3 +# Note terminal (double colon) rules creating runme files to fix possible infinite recursion, +# see https://github.com/swig/swig/pull/688 +ifeq ($(SCRIPTDIR),$(srcdir)) + # in source tree build + ifeq (,$(PY3)) + convert_testcase = + else + convert_testcase = \ if [ -f $(srcdir)/$(py2_runme) ]; then \ $(MAKE) $(SCRIPTDIR)/$(py_runme); \ fi -$(SCRIPTDIR)/$(SCRIPTPREFIX)%$(SCRIPTSUFFIX): $(srcdir)/$(SCRIPTPREFIX)%$(PY2SCRIPTSUFFIX) - test x$< = x$@ || cp $< $@ || exit 1 - test x$(PY3) = x || $(PY2TO3) -w $@ >/dev/null 2>&1 || exit 1 +# For converting python 2 tests into Python 3 tests +$(SCRIPTDIR)/$(SCRIPTPREFIX)%$(SCRIPTSUFFIX):: $(srcdir)/$(SCRIPTPREFIX)%$(PY2SCRIPTSUFFIX) + cp $< $@ + $(PY2TO3) -w $@ >/dev/null 2>&1 + + endif +else + # out of source tree build + ifeq (,$(PY3)) + convert_testcase = \ + if [ -f $(srcdir)/$(py2_runme) ]; then \ + $(MAKE) $(SCRIPTDIR)/$(py_runme); \ + fi + +$(SCRIPTDIR)/$(SCRIPTPREFIX)%$(SCRIPTSUFFIX):: $(srcdir)/$(SCRIPTPREFIX)%$(PY2SCRIPTSUFFIX) + cp $< $@ + + else + convert_testcase = \ + if [ -f $(srcdir)/$(py2_runme) ]; then \ + $(MAKE) $(SCRIPTDIR)/$(py_runme); \ + elif [ -f $(srcdir)/$(py3_runme) ]; then \ + $(MAKE) $(SCRIPTDIR)/$(py3_runme); \ + fi + +# For when there is a _runme3.py instead of a _runme.py, ie a Python 3 only run test +$(SCRIPTDIR)/$(SCRIPTPREFIX)%$(SCRIPTSUFFIX):: $(srcdir)/$(SCRIPTPREFIX)%$(PY3SCRIPTSUFFIX) + cp $< $@ + +# For converting python 2 tests into Python 3 tests +$(SCRIPTDIR)/$(SCRIPTPREFIX)%$(SCRIPTSUFFIX):: $(srcdir)/$(SCRIPTPREFIX)%$(PY2SCRIPTSUFFIX) + cp $< $@ + $(PY2TO3) -w $@ >/dev/null 2>&1 + + endif endif @@ -167,7 +217,7 @@ endif %.clean: @rm -f $*.py @if test -f $(srcdir)/$(py2_runme); then rm -f $(SCRIPTDIR)/$(py3_runme) $(SCRIPTDIR)/$(py3_runme).bak; fi - @if test "x$(SCRIPTDIR)" != "x$(srcdir)"; then rm -f $(SCRIPTDIR)/$(py2_runme); fi + @if test "x$(SCRIPTDIR)" != "x$(srcdir)"; then rm -f $(SCRIPTDIR)/$(py_runme); fi clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' python_clean @@ -176,19 +226,6 @@ clean: rm -f imports_a.py imports_b.py mod_a.py mod_b.py multi_import_a.py rm -f multi_import_b.py packageoption_a.py packageoption_b.py packageoption_c.py -cvsignore: - @echo '*wrap* *.pyc *.so *.dll *.exp *.lib' - @echo Makefile - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.py; done - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do if grep -q $${i}_runme.py CVS/Entries ; then echo $${i}_runme.py; fi; done - @echo clientdata_prop_a.py - @echo clientdata_prop_b.py - @echo imports_a.py - @echo imports_b.py - @echo mod_a.py mod_b.py - @echo hugemod.h hugemod_a.i hugemod_b.i hugemod_a.py hugemod_b.py hugemod_runme.py - @echo template_typedef_import.py - hugemod_runme = hugemod$(SCRIPTPREFIX) hugemod: diff --git a/Examples/test-suite/python/argcargvtest_runme.py b/Examples/test-suite/python/argcargvtest_runme.py index 38843b932..b0345746f 100644 --- a/Examples/test-suite/python/argcargvtest_runme.py +++ b/Examples/test-suite/python/argcargvtest_runme.py @@ -1,21 +1,21 @@ from argcargvtest import * -largs = ['hi', 'hola', 'hello'] +largs = ["hi", "hola", "hello"] if mainc(largs) != 3: raise RuntimeError("bad main typemap") -targs = ('hi', 'hola') -if mainv(targs, 1) != 'hola': +targs = ("hi", "hola") +if mainv(targs, 1) != "hola": print(mainv(targs, 1)) raise RuntimeError("bad main typemap") -targs = ('hi', 'hola') -if mainv(targs, 1) != 'hola': +targs = ("hi", "hola") +if mainv(targs, 1) != "hola": raise RuntimeError("bad main typemap") try: error = 0 - mainv('hello', 1) + mainv("hello", 1) error = 1 except TypeError: pass diff --git a/Examples/test-suite/python/autodoc_runme.py b/Examples/test-suite/python/autodoc_runme.py index af04c8c0e..6002d49fe 100644 --- a/Examples/test-suite/python/autodoc_runme.py +++ b/Examples/test-suite/python/autodoc_runme.py @@ -1,227 +1,79 @@ from autodoc import * +import _autodoc +import comment_verifier +import inspect import sys - def check(got, expected, expected_builtin=None, skip=False): - if not skip: + if is_python_builtin() and skip: + # Only skip for builtins + pass + else: expect = expected if is_python_builtin() and expected_builtin != None: expect = expected_builtin - if expect != got: - raise RuntimeError( - "\n" + "Expected: [" + str(expect) + "]\n" + "Got : [" + str(got) + "]") - - -def is_new_style_class(cls): - return hasattr(cls, "__class__") - -def is_fastproxy(module): - return "new_instancemethod" in module - -if not is_new_style_class(A): - # Missing static methods make this hard to test... skip if -classic is - # used! - sys.exit(0) - -if is_fastproxy(dir()): - # Detect when -fastproxy is specified and skip test as it changes the function names making it - # hard to test... skip until the number of options are reduced in SWIG-3.1 and autodoc is improved - sys.exit(0) + comment_verifier.check(got, expect) # skip builtin check - the autodoc is missing, but it probably should not be skip = True -check(A.__doc__, "Proxy of C++ A class.", "::A") -check(A.funk.__doc__, "just a string.") -check(A.func0.__doc__, - "func0(self, arg2, hello) -> int", - "func0(arg2, hello) -> int") -check(A.func1.__doc__, - "func1(A self, short arg2, Tuple hello) -> int", - "func1(short arg2, Tuple hello) -> int") -check(A.func2.__doc__, - "\n" - " func2(self, arg2, hello) -> int\n" - "\n" - " Parameters\n" - " ----------\n" - " arg2: short\n" - " hello: int tuple[2]\n" - "\n" - " ", - "\n" - "func2(arg2, hello) -> int\n" +check(inspect.getdoc(A), "Proxy of C++ A class.", "::A") +check(inspect.getdoc(A.funk), "just a string.") +check(inspect.getdoc(A.func0), + "func0(self, arg2, hello) -> int") +check(inspect.getdoc(A.func1), + "func1(A self, short arg2, Tuple hello) -> int") +check(inspect.getdoc(A.func2), + "func2(self, arg2, hello) -> int\n" "\n" "Parameters\n" "----------\n" "arg2: short\n" - "hello: int tuple[2]\n" - "\n" - "" - ) -check(A.func3.__doc__, - "\n" - " func3(A self, short arg2, Tuple hello) -> int\n" - "\n" - " Parameters\n" - " ----------\n" - " arg2: short\n" - " hello: int tuple[2]\n" - "\n" - " ", - "\n" - "func3(short arg2, Tuple hello) -> int\n" + "hello: int tuple[2]") +check(inspect.getdoc(A.func3), + "func3(A self, short arg2, Tuple hello) -> int\n" "\n" "Parameters\n" "----------\n" "arg2: short\n" - "hello: int tuple[2]\n" - "\n" - "" - ) + "hello: int tuple[2]") -check(A.func0default.__doc__, - "\n" - " func0default(self, e, arg3, hello, f=2) -> int\n" - " func0default(self, e, arg3, hello) -> int\n" - " ", - "\n" - "func0default(e, arg3, hello, f=2) -> int\n" - "func0default(e, arg3, hello) -> int\n" - "" - ) -check(A.func1default.__doc__, - "\n" - " func1default(A self, A e, short arg3, Tuple hello, double f=2) -> int\n" - " func1default(A self, A e, short arg3, Tuple hello) -> int\n" - " ", - "\n" - "func1default(A e, short arg3, Tuple hello, double f=2) -> int\n" - "func1default(A e, short arg3, Tuple hello) -> int\n" - "" - ) -check(A.func2default.__doc__, - "\n" - " func2default(self, e, arg3, hello, f=2) -> int\n" - "\n" - " Parameters\n" - " ----------\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" - " f: double\n" - "\n" - " func2default(self, e, arg3, hello) -> int\n" - "\n" - " Parameters\n" - " ----------\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" - "\n" - " ", - "\n" - "func2default(e, arg3, hello, f=2) -> int\n" +check(inspect.getdoc(A.func0default), + "func0default(self, e, arg3, hello, f=2) -> int") +check(inspect.getdoc(A.func1default), + "func1default(A self, A e, short arg3, Tuple hello, double f=2) -> int") +check(inspect.getdoc(A.func2default), + "func2default(self, e, arg3, hello, f=2) -> int\n" "\n" "Parameters\n" "----------\n" "e: A *\n" "arg3: short\n" "hello: int tuple[2]\n" - "f: double\n" - "\n" - "func2default(e, arg3, hello) -> int\n" + "f: double") +check(inspect.getdoc(A.func3default), + "func3default(A self, A e, short arg3, Tuple hello, double f=2) -> int\n" "\n" "Parameters\n" "----------\n" "e: A *\n" "arg3: short\n" "hello: int tuple[2]\n" - "\n" - "" - ) -check(A.func3default.__doc__, - "\n" - " func3default(A self, A e, short arg3, Tuple hello, double f=2) -> int\n" - "\n" - " Parameters\n" - " ----------\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" - " f: double\n" - "\n" - " func3default(A self, A e, short arg3, Tuple hello) -> int\n" - "\n" - " Parameters\n" - " ----------\n" - " e: A *\n" - " arg3: short\n" - " hello: int tuple[2]\n" - "\n" - " ", - "\n" - "func3default(A e, short arg3, Tuple hello, double f=2) -> int\n" - "\n" - "Parameters\n" - "----------\n" - "e: A *\n" - "arg3: short\n" - "hello: int tuple[2]\n" - "f: double\n" - "\n" - "func3default(A e, short arg3, Tuple hello) -> int\n" - "\n" - "Parameters\n" - "----------\n" - "e: A *\n" - "arg3: short\n" - "hello: int tuple[2]\n" - "\n" - "" - ) + "f: double") -check(A.func0static.__doc__, - "\n" - " func0static(e, arg2, hello, f=2) -> int\n" - " func0static(e, arg2, hello) -> int\n" - " ", - "\n" - "func0static(e, arg2, hello, f=2) -> int\n" - "func0static(e, arg2, hello) -> int\n" - "" - ) -check(A.func1static.__doc__, - "\n" - " func1static(A e, short arg2, Tuple hello, double f=2) -> int\n" - " func1static(A e, short arg2, Tuple hello) -> int\n" - " ", - "\n" - "func1static(A e, short arg2, Tuple hello, double f=2) -> int\n" - "func1static(A e, short arg2, Tuple hello) -> int\n" - "" - ) -check(A.func2static.__doc__, - "\n" - " func2static(e, arg2, hello, f=2) -> int\n" - "\n" - " Parameters\n" - " ----------\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" - " f: double\n" - "\n" - " func2static(e, arg2, hello) -> int\n" - "\n" - " Parameters\n" - " ----------\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" - "\n" - " ", - "\n" +check(inspect.getdoc(A.func0static), + "func0static(e, arg2, hello, f=2) -> int") +check(inspect.getdoc(_autodoc.A_func0static), + "A_func0static(e, arg2, hello, f=2) -> int") +check(inspect.getdoc(A_func0static), + "A_func0static(e, arg2, hello, f=2) -> int") +check(inspect.getdoc(A.func1static), + "func1static(A e, short arg2, Tuple hello, double f=2) -> int") +check(inspect.getdoc(_autodoc.A_func1static), + "A_func1static(A e, short arg2, Tuple hello, double f=2) -> int") +check(inspect.getdoc(A_func1static), + "A_func1static(A e, short arg2, Tuple hello, double f=2) -> int") +check(inspect.getdoc(A.func2static), "func2static(e, arg2, hello, f=2) -> int\n" "\n" "Parameters\n" @@ -229,39 +81,26 @@ check(A.func2static.__doc__, "e: A *\n" "arg2: short\n" "hello: int tuple[2]\n" - "f: double\n" - "\n" - "func2static(e, arg2, hello) -> int\n" + "f: double") +check(inspect.getdoc(_autodoc.A_func2static), + "A_func2static(e, arg2, hello, f=2) -> int\n" "\n" "Parameters\n" "----------\n" "e: A *\n" "arg2: short\n" "hello: int tuple[2]\n" + "f: double") +check(inspect.getdoc(A_func2static), + "A_func2static(e, arg2, hello, f=2) -> int\n" "\n" - "" - ) -check(A.func3static.__doc__, - "\n" - " func3static(A e, short arg2, Tuple hello, double f=2) -> int\n" - "\n" - " Parameters\n" - " ----------\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" - " f: double\n" - "\n" - " func3static(A e, short arg2, Tuple hello) -> int\n" - "\n" - " Parameters\n" - " ----------\n" - " e: A *\n" - " arg2: short\n" - " hello: int tuple[2]\n" - "\n" - " ", - "\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg2: short\n" + "hello: int tuple[2]\n" + "f: double") +check(inspect.getdoc(A.func3static), "func3static(A e, short arg2, Tuple hello, double f=2) -> int\n" "\n" "Parameters\n" @@ -269,99 +108,174 @@ check(A.func3static.__doc__, "e: A *\n" "arg2: short\n" "hello: int tuple[2]\n" - "f: double\n" - "\n" - "func3static(A e, short arg2, Tuple hello) -> int\n" + "f: double") +check(inspect.getdoc(_autodoc.A_func3static), + "A_func3static(A e, short arg2, Tuple hello, double f=2) -> int\n" "\n" "Parameters\n" "----------\n" "e: A *\n" "arg2: short\n" "hello: int tuple[2]\n" + "f: double") +check(inspect.getdoc(A_func3static), + "A_func3static(A e, short arg2, Tuple hello, double f=2) -> int\n" "\n" - "" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg2: short\n" + "hello: int tuple[2]\n" + "f: double") + +check(inspect.getdoc(A.variable_a), + "variable_a" + ) +check(inspect.getdoc(A.variable_b), + "variable_b : int" + ) +check(inspect.getdoc(A.variable_c), + "variable_c" + ) +check(inspect.getdoc(A.variable_d), + "variable_d : int" ) -if sys.version_info[0:2] > (2, 4): - # Python 2.4 does not seem to work - check(A.variable_a.__doc__, - "A_variable_a_get(self) -> int", - "A.variable_a" - ) - check(A.variable_b.__doc__, - "A_variable_b_get(A self) -> int", - "A.variable_b" - ) - check(A.variable_c.__doc__, - "\n" - "A_variable_c_get(self) -> int\n" +# Check the low-level functions (not present when using -builtin except for the static ones) +if not is_python_builtin(): + check(inspect.getdoc(_autodoc.A_funk), "just a string.") + check(inspect.getdoc(_autodoc.A_func0), + "A_func0(self, arg2, hello) -> int") + check(inspect.getdoc(_autodoc.A_func1), + "A_func1(A self, short arg2, Tuple hello) -> int") + check(inspect.getdoc(_autodoc.A_func2), + "A_func2(self, arg2, hello) -> int\n" "\n" "Parameters\n" "----------\n" - "self: A *\n" - "\n", - "A.variable_c" - ) - check(A.variable_d.__doc__, - "\n" - "A_variable_d_get(A self) -> int\n" + "arg2: short\n" + "hello: int tuple[2]") + check(inspect.getdoc(_autodoc.A_func3), + "A_func3(A self, short arg2, Tuple hello) -> int\n" "\n" "Parameters\n" "----------\n" - "self: A *\n" - "\n", - "A.variable_d" + "arg2: short\n" + "hello: int tuple[2]") + check(inspect.getdoc(_autodoc.A_func0default), + "A_func0default(self, e, arg3, hello, f=2) -> int") + check(inspect.getdoc(_autodoc.A_func1default), + "A_func1default(A self, A e, short arg3, Tuple hello, double f=2) -> int") + check(inspect.getdoc(_autodoc.A_func2default), + "A_func2default(self, e, arg3, hello, f=2) -> int\n" + "\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg3: short\n" + "hello: int tuple[2]\n" + "f: double") + check(inspect.getdoc(_autodoc.A_func3default), + "A_func3default(A self, A e, short arg3, Tuple hello, double f=2) -> int\n" + "\n" + "Parameters\n" + "----------\n" + "e: A *\n" + "arg3: short\n" + "hello: int tuple[2]\n" + "f: double") + check(inspect.getdoc(_autodoc.A_variable_a_set), "A_variable_a_set(self, variable_a)") + check(inspect.getdoc(_autodoc.A_variable_a_get), "A_variable_a_get(self) -> int" ) + check(inspect.getdoc(_autodoc.A_variable_b_set), "A_variable_b_set(A self, int variable_b)") + check(inspect.getdoc(_autodoc.A_variable_b_get), "A_variable_b_get(A self) -> int") + check(inspect.getdoc(_autodoc.A_variable_c_set), + "A_variable_c_set(self, variable_c)\n" + "\n" + "Parameters\n" + "----------\n" + "variable_c: int" ) + check(inspect.getdoc(_autodoc.A_variable_c_get), "A_variable_c_get(self) -> int") + check(inspect.getdoc(_autodoc.A_variable_d_set), + "A_variable_d_set(A self, int variable_d)\n" + "\n" + "Parameters\n" + "----------\n" + "variable_d: int" + ) + check(inspect.getdoc(_autodoc.A_variable_d_get), "A_variable_d_get(A self) -> int") + check(inspect.getdoc(_autodoc.new_C), "new_C(a, b, h) -> C") + check(inspect.getdoc(_autodoc.delete_C), "delete_C(self)") + check(inspect.getdoc(_autodoc.new_D), "new_D(int a, int b, Hola h) -> D") + check(inspect.getdoc(_autodoc.delete_D), "delete_D(D self)") + check(inspect.getdoc(_autodoc.new_E), + "new_E(a, b, h) -> E\n" + "\n" + "Parameters\n" + "----------\n" + "a: special comment for parameter a\n" + "b: another special comment for parameter b\n" + "h: enum Hola" + ) + check(inspect.getdoc(_autodoc.delete_E), "delete_E(self)") + check(inspect.getdoc(_autodoc.new_F), + "new_F(int a, int b, Hola h) -> F\n" + "\n" + "Parameters\n" + "----------\n" + "a: special comment for parameter a\n" + "b: another special comment for parameter b\n" + "h: enum Hola" + ) + check(inspect.getdoc(_autodoc.delete_F), "delete_F(F self)") + check(inspect.getdoc(_autodoc.B_funk), "B_funk(B self, int c, int d) -> int") + check(inspect.getdoc(_autodoc.TInteger_inout), "TInteger_inout(TInteger self, TInteger t) -> TInteger") -check(B.__doc__, +check(inspect.getdoc(B), "Proxy of C++ B class.", "::B" ) -check(C.__init__.__doc__, "__init__(self, a, b, h) -> C", None, skip) -check(D.__init__.__doc__, +check(inspect.getdoc(C.__init__), "__init__(self, a, b, h) -> C", None, skip) +check(inspect.getdoc(D.__init__), "__init__(D self, int a, int b, Hola h) -> D", None, skip) -check(E.__init__.__doc__, +check(inspect.getdoc(E.__init__), + "__init__(self, a, b, h) -> E\n" "\n" - " __init__(self, a, b, h) -> E\n" - "\n" - " Parameters\n" - " ----------\n" - " a: special comment for parameter a\n" - " b: another special comment for parameter b\n" - " h: enum Hola\n" - "\n" - " ", None, skip + "Parameters\n" + "----------\n" + "a: special comment for parameter a\n" + "b: another special comment for parameter b\n" + "h: enum Hola", None, skip ) -check(F.__init__.__doc__, +check(inspect.getdoc(F.__init__), + "__init__(F self, int a, int b, Hola h) -> F\n" "\n" - " __init__(F self, int a, int b, Hola h) -> F\n" - "\n" - " Parameters\n" - " ----------\n" - " a: special comment for parameter a\n" - " b: another special comment for parameter b\n" - " h: enum Hola\n" - "\n" - " ", None, skip + "Parameters\n" + "----------\n" + "a: special comment for parameter a\n" + "b: another special comment for parameter b\n" + "h: enum Hola", None, skip ) -check(B.funk.__doc__, - "funk(B self, int c, int d) -> int", - "funk(int c, int d) -> int") -check(funk.__doc__, "funk(A e, short arg2, int c, int d) -> int") -check(funkdefaults.__doc__, - "\n" - " funkdefaults(A e, short arg2, int c, int d, double f=2) -> int\n" - " funkdefaults(A e, short arg2, int c, int d) -> int\n" - " ", - "\n" - "funkdefaults(A e, short arg2, int c, int d, double f=2) -> int\n" - "funkdefaults(A e, short arg2, int c, int d) -> int\n" - "" - ) +check(inspect.getdoc(B.funk), + "funk(B self, int c, int d) -> int") +check(inspect.getdoc(funk), "funk(A e, short arg2, int c, int d) -> int") +check(inspect.getdoc(funkdefaults), + "funkdefaults(A e, short arg2, int c, int d, double f=2) -> int") -check(func_input.__doc__, "func_input(int * INPUT) -> int") -check(func_output.__doc__, "func_output() -> int") -check(func_inout.__doc__, "func_inout(int * INOUT) -> int") -check(func_cb.__doc__, "func_cb(int c, int d) -> int") -check(banana.__doc__, "banana(S a, S b, int c, Integer d)") +check(inspect.getdoc(func_input), "func_input(int * INPUT) -> int") +check(inspect.getdoc(func_output), "func_output() -> int") +check(inspect.getdoc(func_inout), "func_inout(int * INOUT) -> int") +check(inspect.getdoc(func_cb), "func_cb(int c, int d) -> int") +check(inspect.getdoc(banana), "banana(S a, S b, int c, Integer d)") + +check(inspect.getdoc(TInteger), "Proxy of C++ T< int > class.", "::T< int >") +check(inspect.getdoc(TInteger.__init__), "__init__(TInteger self) -> TInteger", None, skip) +check(inspect.getdoc(TInteger.inout), "inout(TInteger self, TInteger t) -> TInteger") + +check(inspect.getdoc(process), "process(int _from, int _in, int var) -> int") +check(inspect.getdoc(process2), "process2(int _from=0, int _in=1, int var=2) -> int") +check(inspect.getdoc(process3), "process3(int _from, int _in, int var) -> int") +check(inspect.getdoc(process4), "process4(int _from=0, int _in=1, int var=2) -> int") + +check(inspect.getdoc(process_complex_defval), "process_complex_defval(val=PROCESS_DEFAULT_VALUE, factor=some_type(-1)) -> int") diff --git a/Examples/test-suite/python/callback_runme.py b/Examples/test-suite/python/callback_runme.py index ef7baad4e..de8a372f6 100644 --- a/Examples/test-suite/python/callback_runme.py +++ b/Examples/test-suite/python/callback_runme.py @@ -13,6 +13,10 @@ if foobar(3, _callback.foo) != foo(3): if foobar(3, foo) != foo(3): raise RuntimeError +# Needs some more work for -builtin +# if foobar(3, A.bar) != A.bar(3): +# raise RuntimeError + if foobar(3, A_bar) != A_bar(3): raise RuntimeError diff --git a/Examples/test-suite/python/char_binary_runme.py b/Examples/test-suite/python/char_binary_runme.py index 34caa3208..0425fe1c9 100644 --- a/Examples/test-suite/python/char_binary_runme.py +++ b/Examples/test-suite/python/char_binary_runme.py @@ -1,26 +1,26 @@ from char_binary import * t = Test() -if t.strlen('hile') != 4: - print t.strlen('hile') +if t.strlen("hile") != 4: + print t.strlen("hile") raise RuntimeError, "bad multi-arg typemap" -if t.ustrlen('hile') != 4: - print t.ustrlen('hile') +if t.ustrlen("hile") != 4: + print t.ustrlen("hile") raise RuntimeError, "bad multi-arg typemap" -if t.strlen('hil\0') != 4: +if t.strlen("hil\0") != 4: raise RuntimeError, "bad multi-arg typemap" -if t.ustrlen('hil\0') != 4: +if t.ustrlen("hil\0") != 4: raise RuntimeError, "bad multi-arg typemap" # # creating a raw char* # pc = new_pchar(5) -pchar_setitem(pc, 0, 'h') -pchar_setitem(pc, 1, 'o') -pchar_setitem(pc, 2, 'l') -pchar_setitem(pc, 3, 'a') +pchar_setitem(pc, 0, "h") +pchar_setitem(pc, 1, "o") +pchar_setitem(pc, 2, "l") +pchar_setitem(pc, 3, "a") pchar_setitem(pc, 4, 0) diff --git a/Examples/test-suite/python/comment_verifier.py b/Examples/test-suite/python/comment_verifier.py new file mode 100644 index 000000000..653cb4940 --- /dev/null +++ b/Examples/test-suite/python/comment_verifier.py @@ -0,0 +1,26 @@ +def check(got, expected, expected_builtin=None): + if got is None: # Absence of comment is equivalent to empty comment. + got = "" + + if got != expected: + import re + p = re.compile(r"^[+-]([^+-].*\S)?(\s+)$", re.M) + + def make_trailing_spaces_visible(str): + def replace_trailing_spaces(match): + res = match.group(0) + spaces = match.group(2) + if spaces is not None: + res = res + "{+%d trailing spaces}" % len(spaces) + return res + return re.sub(p, replace_trailing_spaces, str) + + from difflib import unified_diff + diff = unified_diff(expected.splitlines(True), + got.splitlines(True), "expected", "got") + lines = [] + for line in diff: + line = make_trailing_spaces_visible(line.strip("\r\n")) + lines.append(line + "\n") + + raise RuntimeError("Comments don't match:\n" + "".join(lines)) diff --git a/Examples/test-suite/python/complextest_runme.py b/Examples/test-suite/python/complextest_runme.py index 7dd7f5a3b..5cfc7ccab 100644 --- a/Examples/test-suite/python/complextest_runme.py +++ b/Examples/test-suite/python/complextest_runme.py @@ -8,10 +8,23 @@ if complextest.Conj(a) != a.conjugate(): if complextest.Conjf(a) != a.conjugate(): raise RuntimeError, "bad complex mapping" +if complextest.Conj2(a) != a.conjugate(): + raise RuntimeError, "bad complex mapping" + +if complextest.Conjf2(a) != a.conjugate(): + raise RuntimeError, "bad complex mapping" + v = (complex(1, 2), complex(2, 3), complex(4, 3), 1) -try: - complextest.Copy_h(v) -except: - pass +if len(complextest.CopyHalf(v)) != 2: + raise RuntimeError("CopyHalf failed") + +if len(complextest.CopyHalfRef(v)) != 2: + raise RuntimeError("CopyHalfRef failed") + +p = complextest.ComplexPair() +p.z1 = complex(0, 1) +p.z2 = complex(0, -1) +if complextest.Conj(p.z2) != p.z1: + raise RuntimeError, "bad complex mapping" diff --git a/Examples/test-suite/python/cpp11_alternate_function_syntax_runme.py b/Examples/test-suite/python/cpp11_alternate_function_syntax_runme.py index 363736a84..cc7b5cd91 100644 --- a/Examples/test-suite/python/cpp11_alternate_function_syntax_runme.py +++ b/Examples/test-suite/python/cpp11_alternate_function_syntax_runme.py @@ -4,11 +4,20 @@ a = cpp11_alternate_function_syntax.SomeStruct() res = a.addNormal(4, 5) if res != 9: - raise RuntimeError, ("SomeStruct::addNormal(4,5) returns ", - res, " should be 9.") - + raise RuntimeError, ("SomeStruct::addNormal(4,5) returns ", res, " should be 9.") res = a.addAlternate(4, 5) if res != 9: - raise RuntimeError, ("SomeStruct::addAlternate(4,5) returns ", - res, " should be 9.") + raise RuntimeError, ("SomeStruct::addAlternate(4,5) returns ", res, " should be 9.") + +res = a.addAlternateConst(4, 5) +if res != 9: + raise RuntimeError, ("SomeStruct::addAlternateConst(4,5) returns ", res, " should be 9.") + +res = a.addAlternateNoExcept(4, 5) +if res != 9: + raise RuntimeError, ("SomeStruct::addAlternateNoExcept(4,5) returns ", res, " should be 9.") + +res = a.addAlternateConstNoExcept(4, 5) +if res != 9: + raise RuntimeError, ("SomeStruct::addAlternateConstNoExcept(4,5) returns ", res, " should be 9.") diff --git a/Examples/test-suite/python/cpp11_final_directors_runme.py b/Examples/test-suite/python/cpp11_final_directors_runme.py new file mode 100644 index 000000000..2e5f8af96 --- /dev/null +++ b/Examples/test-suite/python/cpp11_final_directors_runme.py @@ -0,0 +1,11 @@ +import cpp11_final_directors + +class Derived2(cpp11_final_directors.Derived): + + def meth(self): + return 3 + + +b = Derived2() +if b.meth() != 3: + raise RuntimeError diff --git a/Examples/test-suite/python/cpp11_hash_tables_runme.py b/Examples/test-suite/python/cpp11_hash_tables_runme.py new file mode 100644 index 000000000..7b772ff9a --- /dev/null +++ b/Examples/test-suite/python/cpp11_hash_tables_runme.py @@ -0,0 +1,60 @@ +import cpp11_hash_tables + +def swig_assert_equal(a, b): + if a != b: + raise RuntimeError(str(a) + " != " + str(b)) + +for x in [cpp11_hash_tables.MapIntInt({1:7}), + cpp11_hash_tables.MultiMapIntInt({1:7}), + cpp11_hash_tables.UnorderedMapIntInt({1:7}), + cpp11_hash_tables.UnorderedMultiMapIntInt({1:7}) + ]: + + swig_assert_equal([(k, v) for k, v in x.iteritems()], [(1, 7)]) + swig_assert_equal(x.keys(), [1]) + swig_assert_equal(x.values(), [7]) + swig_assert_equal(x.items(), [(1, 7)]) + swig_assert_equal([k for k in x], [1]) + swig_assert_equal([i for i in x.iterkeys()], [1]) + swig_assert_equal([i for i in x.itervalues()], [7]) + swig_assert_equal([i for i in x.iteritems()], [(1, 7)]) + + swig_assert_equal(x[1], 7) + swig_assert_equal(2 in x, False) + x[2] = 9 + swig_assert_equal(x[2], 9) + del x[2] + swig_assert_equal(2 in x, False) + swig_assert_equal(x.empty(), False) + del x[1] + swig_assert_equal(x.empty(), True) + swig_assert_equal(1 in x, False) + +for x in [cpp11_hash_tables.MultiMapIntInt({1:7}), + cpp11_hash_tables.UnorderedMultiMapIntInt({1:7})]: + x[1] = 9 + swig_assert_equal(sorted([v for k, v in x.iteritems()]), [7, 9]) + swig_assert_equal(len(x), 2) + +for x in [cpp11_hash_tables.SetInt([1]), + cpp11_hash_tables.MultiSetInt([1]), + cpp11_hash_tables.UnorderedSetInt([1]), + cpp11_hash_tables.UnorderedMultiSetInt([1])]: + + swig_assert_equal([e for e in x], [1]) + swig_assert_equal(x[0], 1) + + swig_assert_equal(1 in x, True) + swig_assert_equal(2 in x, False) + x.append(2) + swig_assert_equal(2 in x, True) + x.erase(2) + swig_assert_equal(x.empty(), False) + x.erase(1) + swig_assert_equal(x.empty(), True) + +for x in [cpp11_hash_tables.MultiSetInt([1]), + cpp11_hash_tables.UnorderedMultiSetInt([1])]: + x.append(1) + swig_assert_equal(x.count(1), 2) + swig_assert_equal(len(x), 2) diff --git a/Examples/test-suite/python/cpp11_raw_string_literals_runme.py b/Examples/test-suite/python/cpp11_raw_string_literals_runme.py index 29e53c6a7..6a587b860 100644 --- a/Examples/test-suite/python/cpp11_raw_string_literals_runme.py +++ b/Examples/test-suite/python/cpp11_raw_string_literals_runme.py @@ -1,4 +1,5 @@ from cpp11_raw_string_literals import * +import inspect if cvar.L != 100: raise RuntimeError @@ -46,3 +47,29 @@ if cvar.ff != "I'm a \"raw wide\" \\ string.": if cvar.gg != "I'm a \"raw UTF-8\" \\ string.": raise RuntimeError, cvar.gg + + +def check(got, expected): + expected_list = expected.split("\n") + got_list = got.split("\n") + + if expected_list != got_list: + raise RuntimeError("\n" + "Expected: " + str(expected_list) + "\n" + "Got : " + str(got_list)) + +# When getting docstrings, use inspect.getdoc(x) instead of x.__doc__ otherwise the different options +# such as -O and -builtin may produce different initial indentation. +check(inspect.getdoc(RawStringDoc.WW), "Single line documentation comment") +check(inspect.getdoc(RawStringDoc.XX), +"""Multi-line +documentation +comment""") +check(inspect.getdoc(RawStringDoc.YY), """Single line "raw string" documentation comment""") +check(inspect.getdoc(RawStringDoc.ZZ), +"""Documentation comment + +as a "raw string" +on multiple lines including a \ backslash""") + +check(mm, """)I'm an "ascii" \ string constant with multiple + +lines.""") diff --git a/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py b/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py new file mode 100644 index 000000000..d3aa98c47 --- /dev/null +++ b/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py @@ -0,0 +1,45 @@ +import cpp11_ref_qualifiers + +h = cpp11_ref_qualifiers.Host() + +# Basic testing +h.h1() +h.h2() +h.h6() +h.h7() + +h.h() + +# %feature testing +f = cpp11_ref_qualifiers.Features() +if f.F1() != "F1": + raise RuntimeException("Fail") +if f.F2() != "F2": + raise RuntimeException("Fail") +if f.F3() != "F3": + raise RuntimeException("Fail") + +if f.C1(0) != "C1": + raise RuntimeException("Fail") +if f.C2(0) != "C2": + raise RuntimeException("Fail") +if f.C3(0) != "C3": + raise RuntimeException("Fail") + +# %rename testing +r = cpp11_ref_qualifiers.Renames() +r.RR1() +r.RR2() +r.RR3() + +r.SS1(0) +r.SS2(0) +r.SS3(0) + +# Conversion operators +co = cpp11_ref_qualifiers.ConversionOperators() +s = co.StringConvertCopy() +s = co.StringConvertMove() + +co2 = cpp11_ref_qualifiers.ConversionOperators2() +s = co2.StringConvertMove() diff --git a/Examples/test-suite/python/cpp11_ref_qualifiers_rvalue_unignore_runme.py b/Examples/test-suite/python/cpp11_ref_qualifiers_rvalue_unignore_runme.py new file mode 100644 index 000000000..6352c79c2 --- /dev/null +++ b/Examples/test-suite/python/cpp11_ref_qualifiers_rvalue_unignore_runme.py @@ -0,0 +1,4 @@ +import cpp11_ref_qualifiers_rvalue_unignore + +cpp11_ref_qualifiers_rvalue_unignore.RefQualifier().m1() +cpp11_ref_qualifiers_rvalue_unignore.RefQualifier().m2() diff --git a/Examples/test-suite/python/cpp11_shared_ptr_overload_runme.py b/Examples/test-suite/python/cpp11_shared_ptr_overload_runme.py new file mode 100644 index 000000000..6b179cb6d --- /dev/null +++ b/Examples/test-suite/python/cpp11_shared_ptr_overload_runme.py @@ -0,0 +1,45 @@ +import cpp11_shared_ptr_overload +from cpp11_shared_ptr_overload import MyType + +# ref +ret = cpp11_shared_ptr_overload.UseA(MyType("123")) +if ret != "123 ref": raise RuntimeError("UseA fail:" + ret) + +ret = cpp11_shared_ptr_overload.UseB(0, MyType("123")) +if ret != "123 ref": raise RuntimeError("UseB fail:" + ret) + +ret = cpp11_shared_ptr_overload.UseC(0, MyType("123"), MyType("456")) +if ret != "123 ref": raise RuntimeError("UseC fail:" + ret) + +# sharedptr +ret = cpp11_shared_ptr_overload.UseX(MyType("123")) +if ret != "123 sharedptr": raise RuntimeError("UseX fail:" + ret) + +ret = cpp11_shared_ptr_overload.UseY(0, MyType("123")) +if ret != "123 sharedptr": raise RuntimeError("UseY fail:" + ret) + +ret = cpp11_shared_ptr_overload.UseZ(0, MyType("123"), MyType("456")) +if ret != "123 sharedptr": raise RuntimeError("UseZ fail:" + ret) + +# Combo1-4 +ret = cpp11_shared_ptr_overload.Combo1(MyType("XXX")) +if ret != "XXXCombo1": raise RuntimeError("Combo1 fail:" + ret) + +ret = cpp11_shared_ptr_overload.Combo2(MyType("XXX")) +if ret != "XXXCombo2": raise RuntimeError("Combo2 fail:" + ret) + +ret = cpp11_shared_ptr_overload.Combo3(MyType("XXX")) +if ret != "XXXCombo3": raise RuntimeError("Combo3 fail:" + ret) + +ret = cpp11_shared_ptr_overload.Combo4(MyType("XXX")) +if ret != "XXXCombo4": raise RuntimeError("Combo4 fail:" + ret) + +# Combo5-7 +ret = cpp11_shared_ptr_overload.Combo5(MyType("XXX")) +if ret != "XXXCombo5": raise RuntimeError("Combo5 fail:" + ret) + +ret = cpp11_shared_ptr_overload.Combo6(MyType("XXX")) +if ret != "XXXCombo6": raise RuntimeError("Combo6 fail:" + ret) + +ret = cpp11_shared_ptr_overload.Combo7(MyType("XXX")) +if ret != "XXXCombo7": raise RuntimeError("Combo7 fail:" + ret) diff --git a/Examples/test-suite/python/cpp11_li_std_array_runme.py b/Examples/test-suite/python/cpp11_std_array_runme.py similarity index 99% rename from Examples/test-suite/python/cpp11_li_std_array_runme.py rename to Examples/test-suite/python/cpp11_std_array_runme.py index 3b1ceb2f8..e5e7373dd 100644 --- a/Examples/test-suite/python/cpp11_li_std_array_runme.py +++ b/Examples/test-suite/python/cpp11_std_array_runme.py @@ -1,4 +1,4 @@ -from cpp11_li_std_array import * +from cpp11_std_array import * import sys diff --git a/Examples/test-suite/python/cpp11_template_typedefs_runme.py b/Examples/test-suite/python/cpp11_template_typedefs_runme.py new file mode 100644 index 000000000..4d6fc2629 --- /dev/null +++ b/Examples/test-suite/python/cpp11_template_typedefs_runme.py @@ -0,0 +1,43 @@ +from cpp11_template_typedefs import * + +t = create_TypedefName() +if type(t).__name__ != "SomeTypeInt5": + raise RuntimeError("type(t) is '%s' and should be 'SomeTypeInt5'" % type(t).__name__) + +if t.a != "hello": + raise RuntimeError("t.a should be 'hello'") +if t.b != 10: + raise RuntimeError("t.b should be 10") +if t.get_n() != 5: + raise RuntimeError("t.get_n() should be 5") + +t_bool = create_TypedefNameBool() +if type(t_bool).__name__ != "SomeTypeBool5": + raise RuntimeError("type(t_bool) is '%s' and should be 'SomeTypeBool5'" % type(t_bool).__name__) + +if t_bool.a != "hello": + raise RuntimeError("t_bool.a should be 'hello'") +if t_bool.b != True: + raise RuntimeError("t_bool.b should be True") +if t_bool.get_n() != 15: + raise RuntimeError("t_bool.get_n() should be 15") + +if get_SomeType_b(t) != 10: + raise RuntimeError("get_SomeType_b(t) should be 10") + +if get_SomeType_b2(t) != 10: + raise RuntimeError("get_SomeType_b2(t) should be 10") + +t2 = SomeTypeInt4() +t2.b = 0 +t3 = identity(t2) +t3.b = 5 +if t2.b != 5: + raise RuntimeError("t2.b should be 5") + +if get_bucket_allocator1() != 1: + raise RuntimeError("bucket_allocator1 should be 1") + +# SWIG doesn't handle ::MyClass as a template argument. Skip this test. +#if get_bucket_allocator2() != 2: +# raise RuntimeError("bucket_allocator2 should be 2") diff --git a/Examples/test-suite/python/cpp14_binary_integer_literals_runme.py b/Examples/test-suite/python/cpp14_binary_integer_literals_runme.py new file mode 100644 index 000000000..8274ec6b5 --- /dev/null +++ b/Examples/test-suite/python/cpp14_binary_integer_literals_runme.py @@ -0,0 +1,16 @@ +from cpp14_binary_integer_literals import * + +if cvar.b1 != 1: + raise RuntimeError + +if cvar.b2 != 2: + raise RuntimeError + +if cvar.b3 != 3: + raise RuntimeError + +if cvar.b4 != 4: + raise RuntimeError + +if cvar.b5 != 5: + raise RuntimeError diff --git a/Examples/test-suite/python/cpp17_hex_floating_literals_runme.py b/Examples/test-suite/python/cpp17_hex_floating_literals_runme.py new file mode 100644 index 000000000..ed9f4d26b --- /dev/null +++ b/Examples/test-suite/python/cpp17_hex_floating_literals_runme.py @@ -0,0 +1,28 @@ +from cpp17_hex_floating_literals import * + +if cvar.f1 != 0.: + raise RuntimeError + +if cvar.f2 != 0.: + raise RuntimeError + +if cvar.f3 != 0.: + raise RuntimeError + +if cvar.f4 != 7.5: + raise RuntimeError + +if cvar.f5 != 20.: + raise RuntimeError + +if cvar.f6 != 64.: + raise RuntimeError + +if cvar.f7 != 11452.: + raise RuntimeError + +if cvar.f8 != 149140.: + raise RuntimeError + +if cvar.f9 != 18253638.: + raise RuntimeError diff --git a/Examples/test-suite/python/cpp17_nested_namespaces_runme.py b/Examples/test-suite/python/cpp17_nested_namespaces_runme.py new file mode 100644 index 000000000..562216625 --- /dev/null +++ b/Examples/test-suite/python/cpp17_nested_namespaces_runme.py @@ -0,0 +1,18 @@ +from cpp17_nested_namespaces import * + +A1Struct().A1Method() +B1Struct().B1Method() +C1Struct().C1Method() +createA1Struct().A1Method() +createB1Struct().B1Method() +createC1Struct().C1Method() + +B2Struct().B2Method() +C2Struct().C2Method() +createB2Struct().B2Method() +createC2Struct().C2Method() + +B3Struct().B3Method() +C3Struct().C3Method() +createB3Struct().B3Method() +createC3Struct().C3Method() diff --git a/Examples/test-suite/python/cpp17_u8_char_literals_runme.py b/Examples/test-suite/python/cpp17_u8_char_literals_runme.py new file mode 100644 index 000000000..e2f8897f3 --- /dev/null +++ b/Examples/test-suite/python/cpp17_u8_char_literals_runme.py @@ -0,0 +1,10 @@ +from cpp17_u8_char_literals import * + +if cvar.a != "a": + raise RuntimeError + +if cvar.u != "u": + raise RuntimeError + +if cvar.u8 != "8": + raise RuntimeError diff --git a/Examples/test-suite/python/cpp_static_runme.py b/Examples/test-suite/python/cpp_static_runme.py index 1c7705f3e..cd7398fbb 100644 --- a/Examples/test-suite/python/cpp_static_runme.py +++ b/Examples/test-suite/python/cpp_static_runme.py @@ -2,17 +2,71 @@ from cpp_static import * -def is_new_style_class(cls): - return hasattr(cls, "__class__") +StaticFunctionTest.static_func() +StaticFunctionTest.static_func_2(1) +StaticFunctionTest.static_func_3(1, 2) -if is_new_style_class(StaticFunctionTest): - StaticFunctionTest.static_func() - StaticFunctionTest.static_func_2(1) - StaticFunctionTest.static_func_3(1, 2) -else: - StaticFunctionTest().static_func() - StaticFunctionTest().static_func_2(1) - StaticFunctionTest().static_func_3(1, 2) -StaticMemberTest.static_int = 10 -if not StaticMemberTest.static_int == 10: - raise RuntimeError("static_int not 10") +if is_python_builtin(): + if not StaticMemberTest.static_int == 99: raise RuntimeError("static_int not 99") + if not StaticMemberTest.grab_int() == 99: raise RuntimeError("static_int not 99") + StaticMemberTest.static_int = 10 + if not StaticMemberTest.static_int == 10: raise RuntimeError("static_int not 10") + if not StaticMemberTest.grab_int() == 10: raise RuntimeError("static_int not 10") + + if not StaticBase.statty == 11: raise RuntimeError("statty not 11") + if not StaticBase.grab_statty_base() == 11: raise RuntimeError("statty not 11") + if not StaticDerived.statty == 111: raise RuntimeError("statty not 111") + if not StaticDerived.grab_statty_derived() == 111: raise RuntimeError("statty not 111") + StaticBase.statty = 22 + StaticDerived.statty = 222 + if not StaticBase.statty == 22: raise RuntimeError("statty not 22") + if not StaticBase.grab_statty_base() == 22: raise RuntimeError("statty not 22") + if not StaticDerived.statty == 222: raise RuntimeError("statty not 222") + if not StaticDerived.grab_statty_derived() == 222: raise RuntimeError("statty not 222") + + # Restore + StaticMemberTest.static_int = 99 + StaticBase.statty = 11 + StaticDerived.statty = 111 + +if not cvar.StaticMemberTest_static_int == 99: raise RuntimeError("cvar static_int not 99") +if not StaticMemberTest.grab_int() == 99: raise RuntimeError("cvar static_int not 99") +cvar.StaticMemberTest_static_int = 10 +if not cvar.StaticMemberTest_static_int == 10: raise RuntimeError("cvar static_int not 10") +if not StaticMemberTest.grab_int() == 10: raise RuntimeError("cvar static_int not 10") + +if not cvar.StaticBase_statty == 11: raise RuntimeError("cvar statty not 11") +if not StaticBase.grab_statty_base() == 11: raise RuntimeError("cvar statty not 11") +if not cvar.StaticDerived_statty == 111: raise RuntimeError("cvar statty not 111") +if not StaticDerived.grab_statty_derived() == 111: raise RuntimeError("cvar statty not 111") +cvar.StaticBase_statty = 22 +cvar.StaticDerived_statty = 222 +if not cvar.StaticBase_statty == 22: raise RuntimeError("cvar statty not 22") +if not StaticBase.grab_statty_base() == 22: raise RuntimeError("cvar statty not 22") +if not cvar.StaticDerived_statty == 222: raise RuntimeError("cvar statty not 222") +if not StaticDerived.grab_statty_derived() == 222: raise RuntimeError("cvar statty not 222") + +# Restore +cvar.StaticMemberTest_static_int = 99 +cvar.StaticBase_statty = 11 +cvar.StaticDerived_statty = 111 + +# Low-level layer testing +if not is_python_builtin(): + from cpp_static import _cpp_static + if not _cpp_static.StaticMemberTest_static_int_get() == 99: raise RuntimeError("low-level static_int not 99") + if not StaticMemberTest.grab_int() == 99: raise RuntimeError("low-level static_int not 99") + _cpp_static.StaticMemberTest_static_int_set(10) + if not _cpp_static.StaticMemberTest_static_int_get() == 10: raise RuntimeError("low-level static_int not 10") + if not StaticMemberTest.grab_int() == 10: raise RuntimeError("low-level static_int not 10") + + if not _cpp_static.StaticBase_statty_get() == 11: raise RuntimeError("low-level statty not 11") + if not StaticBase.grab_statty_base() == 11: raise RuntimeError("low-level statty not 11") + if not _cpp_static.StaticDerived_statty_get() == 111: raise RuntimeError("low-level statty not 111") + if not StaticDerived.grab_statty_derived() == 111: raise RuntimeError("low-level statty not 111") + _cpp_static.StaticBase_statty_set(22) + _cpp_static.StaticDerived_statty_set(222) + if not _cpp_static.StaticBase_statty_get() == 22: raise RuntimeError("low-level statty not 22") + if not StaticBase.grab_statty_base() == 22: raise RuntimeError("low-level statty not 22") + if not _cpp_static.StaticDerived_statty_get() == 222: raise RuntimeError("low-level statty not 222") + if not StaticDerived.grab_statty_derived() == 222: raise RuntimeError("low-level statty not 222") diff --git a/Examples/test-suite/python/default_args_c_runme.py b/Examples/test-suite/python/default_args_c_runme.py index 5985fd75c..65ca9178f 100644 --- a/Examples/test-suite/python/default_args_c_runme.py +++ b/Examples/test-suite/python/default_args_c_runme.py @@ -4,3 +4,23 @@ if default_args_c.foo1() != 1: raise RuntimeError("failed") if default_args_c.foo43() != 43: raise RuntimeError("failed") + +f = default_args_c.FooStruct() +f.no_arg() +f.one_req(None) +f.one_opt() +f.one_opt(None) +f.two_arg(None) +f.two_arg(None, None) + +default_args_c.StaticStruct.no_arg() +default_args_c.StaticStruct.one_req(None) +default_args_c.StaticStruct.one_opt() +default_args_c.StaticStruct.one_opt(None) +default_args_c.StaticStruct.two_arg(None) +default_args_c.StaticStruct.two_arg(None, None) + +default_args_c.global_opts1() +default_args_c.global_opts1(None) +default_args_c.global_opts2(None) +default_args_c.global_opts2(None, None) diff --git a/Examples/test-suite/python/default_args_runme.py b/Examples/test-suite/python/default_args_runme.py index 9d275e4a1..14ef8c594 100644 --- a/Examples/test-suite/python/default_args_runme.py +++ b/Examples/test-suite/python/default_args_runme.py @@ -2,10 +2,6 @@ # the use of __main__ and the run function -def is_new_style_class(cls): - return hasattr(cls, "__class__") - - def run(module_name): default_args = __import__(module_name) ec = default_args.EnumClass() @@ -32,6 +28,8 @@ def run(module_name): f.newname() f.newname(1) + f.defaulted1() + f.defaulted2() if f.double_if_void_ptr_is_null(2, None) != 4: raise RuntimeError @@ -99,10 +97,7 @@ def run(module_name): if error: raise RuntimeError("Foo::meth ignore is not working") - if is_new_style_class(default_args.Klass): - Klass_inc = default_args.Klass.inc - else: - Klass_inc = default_args.Klass_inc + Klass_inc = default_args.Klass.inc if Klass_inc(100, default_args.Klass(22)).val != 122: raise RuntimeError("Klass::inc failed") @@ -113,15 +108,54 @@ def run(module_name): if Klass_inc().val != 0: raise RuntimeError("Klass::inc failed") - default_args.trickyvalue1(10) - default_args.trickyvalue1(10, 10) - default_args.trickyvalue2(10) - default_args.trickyvalue2(10, 10) - default_args.trickyvalue3(10) - default_args.trickyvalue3(10, 10) + tricky_failure = False + tricky = default_args.TrickyInPython() + if tricky.value_m1(10) != -1: + print "trickyvalue_m1 failed" + tricky_failure = True + if tricky.value_m1(10, 10) != 10: + print "trickyvalue_m1 failed" + tricky_failure = True + if tricky.value_0xabcdef(10) != 0xabcdef: + print "trickyvalue_0xabcdef failed" + tricky_failure = True + if tricky.value_0644(10) != 420: + print "trickyvalue_0644 failed" + tricky_failure = True + if tricky.value_perm(10) != 420: + print "trickyvalue_perm failed" + tricky_failure = True + if tricky.value_m01(10) != -1: + print "trickyvalue_m01 failed" + tricky_failure = True + if not tricky.booltest2(): + print "booltest2 failed" + tricky_failure = True + + if tricky.max_32bit_int1() != 0x7FFFFFFF: + print "max_32bit_int1 failed" + tricky_failure = True + if tricky.min_32bit_int1() != -2147483648: + print "min_32bit_int1 failed" + tricky_failure = True + if tricky.max_32bit_int2() != 0x7FFFFFFF: + print "max_32bit_int2 failed" + tricky_failure = True + + tricky.too_big_32bit_int1() + tricky.too_small_32bit_int1() + tricky.too_big_32bit_int2() + tricky.too_small_32bit_int2() + + if tricky_failure: + raise RuntimeError + default_args.seek() default_args.seek(10) + if not default_args.booltest(): + raise RuntimeError("booltest failed") + if default_args.slightly_off_square(10) != 102: raise RuntimeError @@ -136,23 +170,23 @@ def run(module_name): if default_args.CDA().cdefaultargs_test2() != 1: raise RuntimeError - if default_args.chartest1() != 'x': + if default_args.chartest1() != "x": raise RuntimeError - if default_args.chartest2() != '\0': + if default_args.chartest2() != "\0": raise RuntimeError - if default_args.chartest3() != '\1': + if default_args.chartest3() != "\1": raise RuntimeError - if default_args.chartest4() != '\n': + if default_args.chartest4() != "\n": raise RuntimeError - if default_args.chartest5() != 'B': + if default_args.chartest5() != "B": raise RuntimeError - if default_args.chartest6() != 'C': + if default_args.chartest6() != "C": raise RuntimeError if __name__ == "__main__": - run('default_args') + run("default_args") diff --git a/Examples/test-suite/python/director_abstract_runme.py b/Examples/test-suite/python/director_abstract_runme.py index 031c476d8..333b75fe5 100644 --- a/Examples/test-suite/python/director_abstract_runme.py +++ b/Examples/test-suite/python/director_abstract_runme.py @@ -1,10 +1,6 @@ import director_abstract -def is_new_style_class(cls): - return hasattr(cls, "__class__") - - class MyFoo(director_abstract.Foo): def __init__(self): @@ -44,20 +40,12 @@ me1 = MyExample1() if director_abstract.Example1_get_color(me1, 1, 2, 3) != 1: raise RuntimeError -if is_new_style_class(MyExample2): - MyExample2_static = MyExample2 -else: - MyExample2_static = MyExample2(0, 0) me2 = MyExample2(1, 2) -if MyExample2_static.get_color(me2, 1, 2, 3) != 2: +if MyExample2.get_color(me2, 1, 2, 3) != 2: raise RuntimeError -if is_new_style_class(MyExample3): - MyExample3_static = MyExample3 -else: - MyExample3_static = MyExample3() me3 = MyExample3() -if MyExample3_static.get_color(me3, 1, 2, 3) != 3: +if MyExample3.get_color(me3, 1, 2, 3) != 3: raise RuntimeError error = 1 diff --git a/Examples/test-suite/python/director_exception_runme.py b/Examples/test-suite/python/director_exception_runme.py index 892c7e653..06856f30a 100644 --- a/Examples/test-suite/python/director_exception_runme.py +++ b/Examples/test-suite/python/director_exception_runme.py @@ -25,6 +25,13 @@ class MyFoo3(Foo): def ping(self): raise MyException("foo", "bar") +class MyFoo4(Foo): + + def ping(self, *args): + print(type("bad", "call")) # throws TypeError message: type() takes 1 or 3 arguments + return "Foo4.ping" + + # Check that the NotImplementedError raised by MyFoo.ping() is returned by # MyFoo.pong(). ok = 0 @@ -51,7 +58,8 @@ b = launder(a) try: b.pong() except TypeError, e: - if str(e) == "SWIG director type mismatch in output value of type 'std::string'": + # fastdispatch mode adds on Additional Information to the exception message - just check the main exception message exists + if str(e).startswith("SWIG director type mismatch in output value of type 'std::string'"): ok = 1 else: print "Unexpected error message: %s" % str(e) @@ -67,13 +75,29 @@ b = launder(a) try: b.pong() except MyException, e: - if e.msg == 'foobar': + if e.msg == "foobar": ok = 1 else: print "Unexpected error message: %s" % str(e) if not ok: raise RuntimeError + +# Check that the director returns the appropriate TypeError thrown in a director method +ok = 0 +a = MyFoo4() +b = launder(a) +try: + b.pong() +except TypeError as e: + if str(e).startswith("type() takes 1 or 3 arguments"): + ok = 1 + else: + print "Unexpected error message: %s" % str(e) +if not ok: + raise RuntimeError + + # This is expected to fail with -builtin option # Throwing builtin classes as exceptions not supported if not is_python_builtin(): diff --git a/Examples/test-suite/python/director_smartptr_runme.py b/Examples/test-suite/python/director_smartptr_runme.py index c8bab9d7a..23e22d0fb 100644 --- a/Examples/test-suite/python/director_smartptr_runme.py +++ b/Examples/test-suite/python/director_smartptr_runme.py @@ -15,6 +15,20 @@ class director_smartptr_MyBarFoo(Foo): def makeFoo(self): return Foo() +class director_smartptr_MyBarFooDerived(FooDerived): + + def ping(self): + return "director_smartptr_MyBarFooDerived.ping()" + + def pong(self): + return "director_smartptr_MyBarFooDerived.pong();" + self.ping() + + def upcall(self, fooBarPtr): + return "overrideDerived;" + fooBarPtr.FooBarDo() + + def makeFoo(self): + return Foo() + def check(got, expected): if (got != expected): raise RuntimeError, "Failed, got: " + got + " expected: " + expected @@ -35,3 +49,8 @@ myFoo2 = Foo().makeFoo() check(myFoo2.pong(), "Foo::pong();Foo::ping()") check(Foo.callPong(myFoo2), "Foo::pong();Foo::ping()") check(myFoo2.upcall(FooBar()), "Bar::Foo2::Foo2Bar()") + +myBarFooDerived = director_smartptr_MyBarFooDerived() +check(myBarFooDerived.ping(), "director_smartptr_MyBarFooDerived.ping()") +check(FooDerived.callPong(myBarFooDerived), "director_smartptr_MyBarFooDerived.pong();director_smartptr_MyBarFooDerived.ping()") +check(FooDerived.callUpcall(myBarFooDerived, fooBar), "overrideDerived;Bar::Foo2::Foo2Bar()") diff --git a/Examples/test-suite/python/doxygen_alias_runme.py b/Examples/test-suite/python/doxygen_alias_runme.py new file mode 100644 index 000000000..505261bcd --- /dev/null +++ b/Examples/test-suite/python/doxygen_alias_runme.py @@ -0,0 +1,10 @@ +import doxygen_alias +import inspect +import comment_verifier + +comment_verifier.check(inspect.getdoc(doxygen_alias.make_something), + """\ +A function returning something. + +:rtype: :py:class:`Something` +:return: A new object which may be None.""") diff --git a/Examples/test-suite/python/doxygen_basic_notranslate_runme.py b/Examples/test-suite/python/doxygen_basic_notranslate_runme.py new file mode 100644 index 000000000..1e654effc --- /dev/null +++ b/Examples/test-suite/python/doxygen_basic_notranslate_runme.py @@ -0,0 +1,66 @@ +import doxygen_basic_notranslate +import inspect +import string +import sys +import comment_verifier + +comment_verifier.check(inspect.getdoc(doxygen_basic_notranslate.function), + r"""\brief +Brief description. + +The comment text +\author Some author +\return Some number +\sa function2""" +) + +comment_verifier.check(inspect.getdoc(doxygen_basic_notranslate.function1), + r"""Single line comment """ +) +comment_verifier.check(inspect.getdoc(doxygen_basic_notranslate.function2), + r"""A test of a very very very very very very very very very very very very very very very very +very very very very very long comment string.""" +) + +comment_verifier.check(inspect.getdoc(doxygen_basic_notranslate.function3), + r"""*Overload 1:* + +A test for overloaded functions +This is function \b one + +| + +*Overload 2:* + +A test for overloaded functions +This is function \b two""" +) + +comment_verifier.check(inspect.getdoc(doxygen_basic_notranslate.function4), + r"""A test of some mixed tag usage +\if CONDITION +This \a code fragment shows us something \. +\par Minuses: +\arg it's senseless +\arg it's stupid +\arg it's null + +\warning This may not work as expected + +\code +int main() { while(true); } +\endcode +\endif""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_notranslate.function5), + r"""This is a post comment. """ +) +comment_verifier.check(inspect.getdoc(doxygen_basic_notranslate.function6), + r"""Test for default args +@param a Some parameter, default is 42""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_notranslate.function7), + r"""Test for a parameter with difficult type +(mostly for python) +@param a Very strange param""" +) diff --git a/Examples/test-suite/python/doxygen_basic_translate_runme.py b/Examples/test-suite/python/doxygen_basic_translate_runme.py new file mode 100644 index 000000000..9ef8dbd52 --- /dev/null +++ b/Examples/test-suite/python/doxygen_basic_translate_runme.py @@ -0,0 +1,84 @@ +import doxygen_basic_translate +import inspect +import string +import sys +import comment_verifier + +comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function), + """\ +Brief description. + +The comment text. + +Author: Some author + +:rtype: int +:return: Some number + +See also: function2""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function2), + """\ +A test of a very very very very very very very very very very very very very very very very +very very very very very long comment string.""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function3), + """*Overload 1:* + +A test for overloaded functions +This is function **one** + +| + +*Overload 2:* + +A test for overloaded functions +This is function **two**""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function4), + """\ +A test of some mixed tag usage +If: CONDITION { +This *code* fragment shows us something . +Title: Minuses: +* it\'s senseless +* it\'s stupid +* it\'s null + +Warning: This may not work as expected + +.. code-block:: c++ + + int main() { while(true); } + + // Test blank line in code block +}""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function5), + """This is a post comment.""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function6), + """\ +Test for default args +:type a: int +:param a: Some parameter, default is 42""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function7), + """\ +Test for a parameter with difficult type +(mostly for python) +:type a: :py:class:`Shape` +:param a: Very strange param""" +) + +comment_verifier.check(inspect.getdoc(doxygen_basic_translate.Atan2), + """\ +Multiple parameters test. + +:type y: float +:param y: Vertical coordinate. +:type x: float +:param x: Horizontal coordinate. +:rtype: float +:return: Arc tangent of ``y/x``.""" +) diff --git a/Examples/test-suite/python/doxygen_basic_translate_style2_runme.py b/Examples/test-suite/python/doxygen_basic_translate_style2_runme.py new file mode 100644 index 000000000..b75045d59 --- /dev/null +++ b/Examples/test-suite/python/doxygen_basic_translate_style2_runme.py @@ -0,0 +1,82 @@ +import doxygen_basic_translate_style2 +import inspect +import string +import sys +import comment_verifier + +comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function), + """\ +Brief description. + +The comment text. + +Author: Some author + +:rtype: int +:return: Some number + +See also: function2""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function2), + """\ +A test of a very very very very very very very very very very very very very very very very +very very very very very long comment string.""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function3), + """*Overload 1:* +A test for overloaded functions +This is function **one** + +| + +*Overload 2:* +A test for overloaded functions +This is function **two**""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function4), + """\ +A test of some mixed tag usage +If: CONDITION { +This *code* fragment shows us something . +Title: Minuses: +* it\'s senseless +* it\'s stupid +* it\'s null + +Warning: This may not work as expected + +.. code-block:: c++ + + int main() { while(true); } + + // Test blank line in code block +}""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function5), + """This is a post comment.""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function6), + """\ +Test for default args +:type a: int +:param a: Some parameter, default is 42""" +) +comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function7), + """\ +Test for a parameter with difficult type +(mostly for python) +:type a: :py:class:`Shape` +:param a: Very strange param""" +) + +comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.Atan2), + """\ +Multiple parameters test. + +:type y: float +:param y: Vertical coordinate. +:type x: float +:param x: Horizontal coordinate. +:rtype: float +:return: Arc tangent of ``y/x``.""" +) diff --git a/Examples/test-suite/python/doxygen_ignore_runme.py b/Examples/test-suite/python/doxygen_ignore_runme.py new file mode 100644 index 000000000..9a7b2e5df --- /dev/null +++ b/Examples/test-suite/python/doxygen_ignore_runme.py @@ -0,0 +1,17 @@ +import doxygen_ignore +import inspect +import comment_verifier + +comment_verifier.check(inspect.getdoc(doxygen_ignore.func), + """\ +A contrived example of ignoring too many commands in one comment. + + + + + + +This is specific to **Python**. + + +Command ignored, but anything here is still included.""") diff --git a/Examples/test-suite/python/doxygen_misc_constructs_runme.py b/Examples/test-suite/python/doxygen_misc_constructs_runme.py new file mode 100644 index 000000000..11aa53ba3 --- /dev/null +++ b/Examples/test-suite/python/doxygen_misc_constructs_runme.py @@ -0,0 +1,133 @@ +import doxygen_misc_constructs +import inspect +import string +import sys +import comment_verifier + + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.getAddress), + r"""Returns address of file line. + +:type fileName: int +:param fileName: name of the file, where the source line is located +:type line: int +:param line: line number +:type isGetSize: boolean +:param isGetSize: if set, for every object location both address and size are returned + +Connection::getId() """) + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.CConnectionConfig), + r"""This class contains information for connection to winIDEA. Its methods +return reference to self, so we can use it like this: + +CConnectionConfig config = new CConnectionConfig(); +config.discoveryPort(5534).dllPath("C:\\myWinIDEA\\connect.dll").id("main"); + + +All parameters are optional. Set only what is required, default values are +used for unspecified parameters. + + + +advancedWinIDEALaunching.py Python example.""") + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.waitTime), + r"""Determines how long the ``isystem.connect`` should wait for running +instances to respond. Only one of ``lfWaitXXX`` flags from IConnect::ELaunchFlags +may be specified.""" +) + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.getConnection), + r"""This function returns connection id.""" +) + + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.getFirstLetter), + r"" +) + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.ClassWithNestedEnum), + r"""Class description.""" +) + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.showList), + r"""An example of a list in a documentation comment. + + - The first item of the list. + - The second list item, on + several indented lines, + showing that the indentation + is preserved. + - And the final list item after it. + +And this is not a list item any more.""" +) + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.isNoSpaceValidA), + r"""This comment without space after '*' is valid in Doxygen.""" +) + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.isNoSpaceValidB), + r""".This comment without space after '*' is valid in Doxygen.""" +) + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.isNoSpaceValidC), + r"" +) + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.backslashA), + r"""Backslash following``word`` is a valid doxygen command. Output contains +'followingword' with 'word' in code font.""" +) + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.backslashB), + r"""Doxy command without trailing space is ignored - nothing appears +on output. Standalone \ and '\' get to output. +Standalone @ and '@' get to output. +Commands "in quoted \b strings are treated as plain text". +Commands not recognized by Doxygen are ignored. +Backslashes in DOS paths d:and words +following them do not appear on output, we must quote them with +double quotes: "d:\xyz\qwe\myfile", "@something". Single quotes do not help: +'d:'. Escaping works: d:\xyz\qwe\myfile. Unix +paths of course have no such problems: /xyz/qwe/myfile +Commands for escaped symbols: +$ @ \ & ~ < > # % " . :: @text ::text""" +) + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.backslashC), + r"""Backslash e at end of *line* froze SWIG +*with* old comment parser. + +See also: MyClass::fun(char, + float)""" +) + + +comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.cycle), + r"""The next line contains expression: + +['retVal < 10', 'g_counter == 23 && g_mode & 3'] + + +Both words should be emphasized **isystem.connect**. +But not the last period. For **example**, comma should not be emphasized. +Similar **for**: double colon. + +Spaces at the start of line should be taken into account: +:type id: int +:param id: used as prefix in log + statements. The default value is empty string, which is OK if + there is only one app. instance. Example: + + ctrl.setBP("func1"); + + If we set the id to ``main_``, we get: + + main_ctrl.setBP("func1"); + + +:type fileName: string +:param fileName: name of the log file""" +); diff --git a/Examples/test-suite/python/doxygen_parsing_runme.py b/Examples/test-suite/python/doxygen_parsing_runme.py new file mode 100644 index 000000000..80e8892fa --- /dev/null +++ b/Examples/test-suite/python/doxygen_parsing_runme.py @@ -0,0 +1,66 @@ +import doxygen_parsing +import inspect +import string +import os +import sys +import comment_verifier + +comment_verifier.check(inspect.getdoc(doxygen_parsing.someFunction), + "The function comment") +comment_verifier.check(inspect.getdoc(doxygen_parsing.SomeClass), + "The class comment") +comment_verifier.check(inspect.getdoc(doxygen_parsing.SomeStruct), + "The struct comment") +comment_verifier.check(inspect.getdoc(doxygen_parsing.SomeAnotherClass), + "SomeAnotherClass description") + +# There doesn't seem to be any way to specify the doc string for __init__ when +# using "-builtin" (see http://stackoverflow.com/q/11913492/15275), so skip +# this test in this case. +if not doxygen_parsing.is_python_builtin(): + comment_verifier.check(inspect.getdoc(doxygen_parsing.SomeAnotherClass.__init__), + r"""*Overload 1:* +First overloaded constructor. + +| + +*Overload 2:* +Second overloaded constructor.""") + +comment_verifier.check(inspect.getdoc(doxygen_parsing.SomeAnotherClass.classMethod), + r"""The class method comment. + +SomeAnotherClass#classMethodExtended(int, int) a link text""") +comment_verifier.check(inspect.getdoc(doxygen_parsing.SomeAnotherClass.classMethodExtended), + r"""The class method with parameter + +:type a: int +:param a: Parameter a +:type b: int +:param b: Parameter b""" +) +comment_verifier.check(inspect.getdoc(doxygen_parsing.SomeAnotherClass.classMethodExtended2), + r"""The class method with parameter + +:type a: int +:param a: Parameter a +:type b: int +:param b: Parameter b""" +) +comment_verifier.check(inspect.getdoc(doxygen_parsing.SomeAnotherStruct.structMethod), + r"""The struct method comment""") +comment_verifier.check(inspect.getdoc(doxygen_parsing.SomeAnotherStruct.structMethodExtended), + r"""The struct method with parameter + +:type a: int +:param a: Parameter a +:type b: int +:param b: Parameter b""" +) +comment_verifier.check(inspect.getdoc(doxygen_parsing.SomeAnotherStruct.structMethodExtended2), + r"""The struct method with parameter + +:type a: int +:param a: Parameter a +:type b: int +:param b: Parameter b""") diff --git a/Examples/test-suite/python/doxygen_translate_all_tags_runme.py b/Examples/test-suite/python/doxygen_translate_all_tags_runme.py new file mode 100644 index 000000000..df1c0eba5 --- /dev/null +++ b/Examples/test-suite/python/doxygen_translate_all_tags_runme.py @@ -0,0 +1,313 @@ +import doxygen_translate_all_tags +import inspect +import string +import sys +import comment_verifier + + +comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func01), +r"""*Hello* + + + + + +* some list item + +This is attention! +You were warned! + +Authors: lots of them +Author: Zubr + +**boldword** + +Some brief description, +extended to many lines. + +Not everything works right now... +``codeword`` + + + + + +'citationword' + +.. code-block:: c++ + + some test code + +Code immediately following text. Pydoc translation must add an +empty line before: + +.. code-block:: c++ + + more test code""") + +comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func02), +r"""Conditional comment: SOMECONDITION +Some conditional comment +End of conditional comment. + + + + + + + +Copyright: some copyright + +1970 - 2012 + + + + + +Deprecated: Now use another function + +This is very large +and detailed description of some thing""") + +comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func03), +r"""Comment for **func03()**. + + + + + + + + + +*italicword* + +emphazedWord + + + +Example: someFile.txt +Some details on using the example""") + +comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func04), +r""":raises: SuperError + + + +:math:`\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}` + +.. math:: + + \sqrt{(x_2-x_1)^2+(y_2-y_1)^2} + +.. math:: + + \sqrt{(x_2-x_1)^2+(y_2-y_1)^2} + +Math immediately following text. Pydoc translation must add an +empty line before: + +.. math:: + + \sqrt{(x_2-x_1)^2+(y_2-y_1)^2} + + + + + + + + + + + +This will only appear in hmtl""") + +comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func05), +r"""If: ANOTHERCONDITION { + First part of comment + If: SECONDCONDITION { + Nested condition text + }Else if: THIRDCONDITION { + The third condition text + }Else: { The last text block + } +}Else: { Second part of comment + If: CONDITION { + Second part extended + } +} + +If not: SOMECONDITION { + This is printed if not +} + +Image: testImage.bmp("Hello, world!") + + + + + + + + + + + +Some text +describing invariant.""") + +comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func06), +r"""Comment for **func06()**. + + + + +This will only appear in LATeX + + + + +* Some unordered list +* With lots of items +* lots of lots of items + + + + +someMember Some description follows + + + + +This will only appear in man""") + +comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func07), +r"""Comment for **func07()**. + + + + + + +Notes: Here +is the note! + +This is an overloaded member function, provided for convenience. +It differs from the above function only in what argument(s) it accepts. + +someword + + + + + +Title: The paragraph title +The paragraph text. +Maybe even multiline + + + +:type a: int +:param a: the first param""") + +comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func08), +r"""Text after anchor. + + + + + + +'Anchor description' + +'someAnchor' not quoted text is not part of ref tag + +'someAnchor' + + + + + + + + + +Remarks: Some remark text + +Another remarks section + +:rtype: void +:return: Whatever + +:rtype: void +:return: it + +:rtype: void +:return: may return""") + +comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func09), +r"""This will only appear in RTF + + +See also: someOtherMethod + + + +See also: function + +Same as +brief description + + + +Since: version 0.0.0.1 + + + + + + + + + + + + + + + +:raises: superException + +:raises: RuntimeError""") + +comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func10), +r"""TODO: Some very important task + +:type b: float +:param b: B is mentioned again... + + + + + + +very long +text with tags + + + +Version: 0.0.0.2 + +Warning: This is senseless! + + + + +This will only appear in XML + + +Here goes test of symbols: +$ @ \ & ~ < > # % " . :: + +And here goes simple text""") diff --git a/Examples/test-suite/python/doxygen_translate_links_runme.py b/Examples/test-suite/python/doxygen_translate_links_runme.py new file mode 100644 index 000000000..89f276f6e --- /dev/null +++ b/Examples/test-suite/python/doxygen_translate_links_runme.py @@ -0,0 +1,38 @@ +import doxygen_translate_links +import inspect +import string +import sys +import comment_verifier + + +comment_verifier.check(inspect.getdoc(doxygen_translate_links.function), +r"""Testing typenames converting in @ link + +superFunc(int,std::string) +Test for std_string member + + +superFunc(int,long,void*) +Test for simple types + + +superFunc(Shape::superType*) +Test for custom types + + +superFunc(int**[13]) +Test for complex types + + +same works for 'See also:' links: + +See also: superFunc(int,std::string) +See also: superFunc(int,long,void*) +See also: superFunc(Shape::superType*) +See also: superFunc(int**[13]) + +some failing params: + +See also: superFunc() +See also: superFunc() +See also: superFunc()""") diff --git a/Examples/test-suite/python/doxygen_translate_runme.py b/Examples/test-suite/python/doxygen_translate_runme.py new file mode 100644 index 000000000..d698ba873 --- /dev/null +++ b/Examples/test-suite/python/doxygen_translate_runme.py @@ -0,0 +1,260 @@ +import doxygen_translate +import inspect +import string +import sys +import comment_verifier + + +comment_verifier.check(inspect.getdoc(doxygen_translate.function), +r"""*Hello* + +* some list item + +Authors: lots of them + +Author: Zubr + +**boldword** + +``codeword`` + +'citationword' + +.. code-block:: c++ + + some test code + +Conditional comment: SOMECONDITION +Some conditional comment +End of conditional comment. + +Copyright: some copyright + +Deprecated: Now use another function + +*italicword* + +Example: someFile.txt +Some details on using the example + +:raises: SuperError + +If: ANOTHERCONDITION { + First part of comment + If: SECONDCONDITION { + Nested condition text + }Else if: THIRDCONDITION { + The third condition text + }Else: { The last text block + } +}Else: { Second part of comment + If: CONDITION { + Second part extended + } +} + +If not: SOMECONDITION { + This is printed if not +} + +Image: testImage.bmp("Hello, world!") + + + +* Some unordered list +* With lots of items +* lots of lots of items + + + +someMember Some description follows + + + + + + +Notes: Here +is the note! + +This is an overloaded member function, provided for convenience. +It differs from the above function only in what argument(s) it accepts. + +someword + + + +Title: The paragraph title +The paragraph text. +Maybe even multiline + +:type a: int +:param a: the first param + +Remarks: Some remark text + +Another remarks section + +:rtype: int +:return: Whatever + +:rtype: int +:return: it + +:rtype: int +:return: may return + +See also: someOtherMethod + +See also: function + +Since: version 0.0.0.1 + +:raises: superException + +:raises: RuntimeError + +TODO: Some very important task + +:type b: float +:param b: B is mentioned again... + +very long +text with tags + +Version: 0.0.0.2 + +Warning: This is senseless! + +Here goes test of symbols: +$ @ \ & ~ < > # % " . :: + +And here goes simple text""" +) + + + +comment_verifier.check(inspect.getdoc(doxygen_translate.htmlFunction), +r"""Test for html tags. See Doxygen doc for list of tags recognized by Doxygen. + +This is link ("http://acme.com/index.html") +**bold** +Quote: +Quotation block. + ("http://www.worldwildlife.org/who/index.html") + + +center +``this is code`` + + +Starts an item title. + Starts an item description. + + +Starts a piece of text displayed in a typewriter font. + +Starts a section with a specific style (HTML only) + +**Starts a piece of text displayed in an italic font.** + +'Form' does not generate any output. + +-------------------------------------------------------------------- + +# Heading 1 + +## Heading 2 + +### Heading 3 + +*Starts a piece of text displayed in an italic font.* +Input tag. +Image: src="slika.png" +Meta tag. +Multicol is ignored by doxygen. + + + +* List item 1. +* List item 2. + + + +Starts a new paragraph. + +Starts a preformatted fragment. + +Starts a section of text displayed in a smaller font. + +'Starts an inline text fragment with a specific style.' +**Starts a section of bold text.** + Starts a piece of text displayed in subscript. + Starts a piece of text displayed in superscript. + + +Animals +| Column 1 | Column 2 | +----------------------- +| cow | dog | +| cat | mouse | +| horse | parrot | + + +Starts a piece of text displayed in a typewriter font. + +Starts a piece of text displayed in a typewriter font. + + + +* List item 1. +* List item 2. +* List item 3. + + +*Starts a piece of text displayed in an italic font.* + + +underlined \b bold text - doxy commands are ignored inside 'htmlonly' section """) + + +comment_verifier.check(inspect.getdoc(doxygen_translate.htmlTableFunction), +r"""The meaning of flags: + +:type byFlags: int +:param byFlags: bits marking required items: + + | Size in bits| Items Required | + -------------------------------- + | 1 - 8 | 1 | + | 9 - 16 | 2 | + | 17 - 32 | 4 | + + Almost all combinations of above flags are supported by + ``htmlTable...`` functions.""") + + +comment_verifier.check(inspect.getdoc(doxygen_translate.htmlEntitiesFunction), +r"""All entities are treated as commands (C) TM (R) +should work also +& +' +" +` +' +" +" +- +-- + +x +- +. +~ +<= +>= +<-- +--> +Not an html entity - ignored by Doxygen. +Not an &text html entity - ampersand is replaced with entity.""") diff --git a/Examples/test-suite/python/extend_template_method_runme.py b/Examples/test-suite/python/extend_template_method_runme.py new file mode 100644 index 000000000..eb1a82d84 --- /dev/null +++ b/Examples/test-suite/python/extend_template_method_runme.py @@ -0,0 +1,45 @@ +from extend_template_method import * + + +em = ExtendMe() + +ret_double = em.do_stuff_double(1, 1.1) +if ret_double != 1.1: + raise RuntimeError("double failed " + ret_double) +ret_string = em.do_stuff_string(1, "hello there") +if ret_string != "hello there": + raise RuntimeError("string failed " + ret_string) + +ret_double = em.do_overloaded_stuff(1.1) +if ret_double != 1.1: + raise RuntimeError("double failed " + ret_double) +ret_string = em.do_overloaded_stuff("hello there") +if ret_string != "hello there": + raise RuntimeError("string failed " + ret_string) + +if ExtendMe.static_method(123) != 123: + raise RuntimeError("static_method failed") + +em2 = ExtendMe(123) + +em = TemplateExtend() + +ret_double = em.do_template_stuff_double(1, 1.1) +if ret_double != 1.1: + raise RuntimeError("double failed " + ret_double) +ret_string = em.do_template_stuff_string(1, "hello there") +if ret_string != "hello there": + raise RuntimeError("string failed " + ret_string) + + +ret_double = em.do_template_overloaded_stuff(1.1) +if ret_double != 1.1: + raise RuntimeError("double failed " + ret_double) +ret_string = em.do_template_overloaded_stuff("hello there") +if ret_string != "hello there": + raise RuntimeError("string failed " + ret_string) + +if TemplateExtend.static_template_method(123) != 123: + raise RuntimeError("static_template_method failed") + +em2 = TemplateExtend(123) diff --git a/Examples/test-suite/python/funcptr_cpp_runme.py b/Examples/test-suite/python/funcptr_cpp_runme.py index eb113d226..22c50b4e9 100644 --- a/Examples/test-suite/python/funcptr_cpp_runme.py +++ b/Examples/test-suite/python/funcptr_cpp_runme.py @@ -8,3 +8,6 @@ if call3(ADD_BY_REFERENCE, 14, 15) != 29: raise RuntimeError if call1(ADD_BY_VALUE_C, 2, 3) != 5: raise RuntimeError + +if callconst1(ADD_BY_VALUE_C, 2, 3) != 5: + raise RuntimeError diff --git a/Examples/test-suite/python/functors_runme.py b/Examples/test-suite/python/functors_runme.py new file mode 100644 index 000000000..98945a047 --- /dev/null +++ b/Examples/test-suite/python/functors_runme.py @@ -0,0 +1,12 @@ +from functors import * + +a = Functor0(10) +b = Functor1(10) +c = Functor2(10) + +if a()!=-10: + raise RuntimeError("a failed") +if b(1)!=11: + raise RuntimeError("b failed") +if c(1, 2)!=13: + raise RuntimeError("c failed") diff --git a/Examples/test-suite/python/global_namespace_runme.py b/Examples/test-suite/python/global_namespace_runme.py index ac12fe2dc..a47f41047 100644 --- a/Examples/test-suite/python/global_namespace_runme.py +++ b/Examples/test-suite/python/global_namespace_runme.py @@ -1,9 +1,6 @@ from global_namespace import * -def is_new_style_class(cls): - return hasattr(cls, "__class__") - k1 = Klass1() k2 = Klass2() k3 = Klass3() @@ -12,12 +9,8 @@ k5 = Klass5() k6 = Klass6() k7 = Klass7() -if is_new_style_class(KlassMethods): - KlassMethods_static = KlassMethods -else: - KlassMethods_static = KlassMethods() -KlassMethods_static.methodA(k1, k2, k3, k4, k5, k6, k7) -KlassMethods_static.methodB(k1, k2, k3, k4, k5, k6, k7) +KlassMethods.methodA(k1, k2, k3, k4, k5, k6, k7) +KlassMethods.methodB(k1, k2, k3, k4, k5, k6, k7) k1 = getKlass1A() k2 = getKlass2A() @@ -27,8 +20,8 @@ k5 = getKlass5A() k6 = getKlass6A() k7 = getKlass7A() -KlassMethods_static.methodA(k1, k2, k3, k4, k5, k6, k7) -KlassMethods_static.methodB(k1, k2, k3, k4, k5, k6, k7) +KlassMethods.methodA(k1, k2, k3, k4, k5, k6, k7) +KlassMethods.methodB(k1, k2, k3, k4, k5, k6, k7) k1 = getKlass1B() k2 = getKlass2B() @@ -38,21 +31,11 @@ k5 = getKlass5B() k6 = getKlass6B() k7 = getKlass7B() -KlassMethods_static.methodA(k1, k2, k3, k4, k5, k6, k7) -KlassMethods_static.methodB(k1, k2, k3, k4, k5, k6, k7) +KlassMethods.methodA(k1, k2, k3, k4, k5, k6, k7) +KlassMethods.methodB(k1, k2, k3, k4, k5, k6, k7) -if is_new_style_class(XYZMethods): - XYZMethods_static = XYZMethods -else: - XYZMethods_static = XYZMethods() -XYZMethods_static.methodA( - XYZ1(), XYZ2(), XYZ3(), XYZ4(), XYZ5(), XYZ6(), XYZ7()) -XYZMethods_static.methodB( - XYZ1(), XYZ2(), XYZ3(), XYZ4(), XYZ5(), XYZ6(), XYZ7()) +XYZMethods.methodA(XYZ1(), XYZ2(), XYZ3(), XYZ4(), XYZ5(), XYZ6(), XYZ7()) +XYZMethods.methodB(XYZ1(), XYZ2(), XYZ3(), XYZ4(), XYZ5(), XYZ6(), XYZ7()) -if is_new_style_class(TheEnumMethods): - TheEnumMethods_static = TheEnumMethods -else: - TheEnumMethods_static = TheEnumMethods() -TheEnumMethods_static.methodA(theenum1, theenum2, theenum3) -TheEnumMethods_static.methodA(theenum1, theenum2, theenum3) +TheEnumMethods.methodA(theenum1, theenum2, theenum3) +TheEnumMethods.methodA(theenum1, theenum2, theenum3) diff --git a/Examples/test-suite/python/ignore_parameter_runme.py b/Examples/test-suite/python/ignore_parameter_runme.py new file mode 100644 index 000000000..2b5c21235 --- /dev/null +++ b/Examples/test-suite/python/ignore_parameter_runme.py @@ -0,0 +1,23 @@ +from ignore_parameter import * + +def check(a, b): + if a != b: + raise RuntimeError("'%s' != '%s'" % (a, b)) + +check(jaguar(200, 0), "hello") +check(lotus("foo", 1), 101) +check(tvr("bar", 2), 8.8) +check(ferrari(), 101) +check(fiat(17), 17) + +car = SportsCars() +check(car.daimler(200, 0), "hello") +check(car.astonmartin("foo", 1), 101) +check(car.bugatti("bar", 2), 8.8) +check(car.lamborghini(), 101) +check(car.maseratti(289), 289) + +MiniCooper(200, 0) +MorrisMinor("baz", 0) +FordAnglia("quux", 200) +AustinAllegro() diff --git a/Examples/test-suite/python/implicittest_runme.py b/Examples/test-suite/python/implicittest_runme.py index 4646d08c0..625613a95 100644 --- a/Examples/test-suite/python/implicittest_runme.py +++ b/Examples/test-suite/python/implicittest_runme.py @@ -6,9 +6,6 @@ def check(a, b): raise RuntimeError(str(a) + " does not equal " + str(b)) -def is_new_style_class(cls): - return hasattr(cls, "__class__") - #### Class #### # No implicit conversion @@ -16,15 +13,7 @@ check(1, A(1).get()) check(2, A(1.0).get()) check(3, A(B()).get()) check(4, A("hello").get()) -try: - check(3, A(None).get()) - raise RuntimeError -except ValueError: - # ValueError: invalid null reference in method 'new_A', argument 1 of type 'B const &' - # Arguably A(char *) should be chosen, but there is a bug to do with None passed to methods overloaded by value, - # references and pointers to different types, where pointers ought to be - # given a slightly higher precedence. - pass +check(4, A(None).get()) check(1, get(1)) check(2, get(1.0)) @@ -45,17 +34,13 @@ check(2, A_int(1.0).get()) check(3, A_int(B()).get()) check(4, A_int("hello").get()) -if is_new_style_class(A_int): - A_int_static = A_int -else: - A_int_static = A_int(0) -check(1, A_int_static.sget(1)) -check(2, A_int_static.sget(1.0)) -check(3, A_int_static.sget(B())) +check(1, A_int.sget(1)) +check(2, A_int.sget(1.0)) +check(3, A_int.sget(B())) # explicit constructor: try: - check(4, A_int_static.sget("hello")) + check(4, A_int.sget("hello")) raise RuntimeError except TypeError: pass diff --git a/Examples/test-suite/python/keyword_rename_runme.py b/Examples/test-suite/python/keyword_rename_runme.py index 5646ce7d6..0bdd64b10 100644 --- a/Examples/test-suite/python/keyword_rename_runme.py +++ b/Examples/test-suite/python/keyword_rename_runme.py @@ -1,4 +1,6 @@ #!/usr/bin/env python import keyword_rename keyword_rename._in(1) +keyword_rename._in(_except=1) keyword_rename._except(1) +keyword_rename._except(_in=1) diff --git a/Examples/test-suite/python/li_boost_array_runme.py b/Examples/test-suite/python/li_boost_array_runme.py deleted file mode 100644 index 4fa7eb882..000000000 --- a/Examples/test-suite/python/li_boost_array_runme.py +++ /dev/null @@ -1,55 +0,0 @@ -from li_boost_array import * -import sys - - -def failed(a, b, msg): - raise RuntimeError, msg + " " + str(list(a)) + " " + str(list(b)) - - -def compare_sequences(a, b): - if len(a) != len(b): - failed(a, b, "different sizes") - for i in range(len(a)): - if a[i] != b[i]: - failed(a, b, "elements are different") - -def compare_containers(pythonlist, swigarray): - compare_sequences(pythonlist, swigarray) - -ps = [0, 1, 2, 3, 4, 5] - -ai = ArrayInt6(ps) - -compare_containers(ps, ai) - -# Modify content -for i in range(len(ps)): - ps[i] = (ps[i] + 1) * 10 - ai[i] = (ai[i] + 1) * 10 -compare_containers(ps, ai) - -# Empty -ai = ArrayInt6() -compare_containers([0, 0, 0, 0, 0, 0], ai) - -# Check return -compare_containers(arrayOutVal(), [-2, -1, 0, 0, 1, 2]) -compare_containers(arrayOutConstRef(), [-2, -1, 0, 0, 1, 2]) -#compare_containers(arrayOutRef(), [-2, -1, 0, 0, 1, 2]) -#compare_containers(arrayOutPtr(), [-2, -1, 0, 0, 1, 2]) - -# Check passing arguments -ai = arrayInVal([9, 8, 7, 6, 5, 4]) -compare_containers(ai, [90, 80, 70, 60, 50, 40]) - -ai = arrayInConstRef([9, 8, 7, 6, 5, 4]) -compare_containers(ai, [90, 80, 70, 60, 50, 40]) - -#ai = ArrayInt6([9, 8, 7, 6, 5, 4]) -#arrayInRef(ai) -#compare_containers(ai, [90, 80, 70, 60, 50, 40]) - -#ai = ArrayInt6([9, 8, 7, 6, 5, 4]) -#arrayInPtr(ai) -#compare_containers(ai, [90, 80, 70, 60, 50, 40]) - diff --git a/Examples/test-suite/python/li_boost_shared_ptr_bits_runme.py b/Examples/test-suite/python/li_boost_shared_ptr_bits_runme.py index 9b9c7d683..adf9ac4cf 100644 --- a/Examples/test-suite/python/li_boost_shared_ptr_bits_runme.py +++ b/Examples/test-suite/python/li_boost_shared_ptr_bits_runme.py @@ -1,10 +1,6 @@ from li_boost_shared_ptr_bits import * -def is_new_style_class(cls): - return hasattr(cls, "__class__") - - def check(nd): nd.i = 200 i = nd.i @@ -35,7 +31,4 @@ if sum != 66: raise "sum is wrong" ################################ -if is_new_style_class(HiddenDestructor): - p = HiddenDestructor.create() -else: - p = HiddenDestructor_create() +p = HiddenDestructor.create() diff --git a/Examples/test-suite/python/li_boost_shared_ptr_director_runme.py b/Examples/test-suite/python/li_boost_shared_ptr_director_runme.py new file mode 100644 index 000000000..52868eacc --- /dev/null +++ b/Examples/test-suite/python/li_boost_shared_ptr_director_runme.py @@ -0,0 +1,80 @@ +from li_boost_shared_ptr_director import * + +class Derived(Base): + def __init__(self, flag): + self.return_none = flag + Base.__init__(self) + + def ret_c_shared_ptr(self): + if self.return_none: + return None + else: + return C() + + def ret_c_by_value(self): + return C() + + def take_c_by_value(self,c): + return c.get_m() + + def take_c_by_ref(self,c): + return c.get_m() + + def take_c_by_pointer(self,c): + if c: + return c.get_m() + else: + return -2 + + def take_c_by_pointer_ref(self,c): + if c: + return c.get_m() + else: + return -3 + + def take_c_shared_ptr_by_value(self,c): + if c: + return c.get_m() + else: + return -4 + + def take_c_shared_ptr_by_ref(self,c): + if c: + return c.get_m() + else: + return -5 + + def take_c_shared_ptr_by_pointer(self,c): + if c: + return c.get_m() + else: + return -6 + + def take_c_shared_ptr_by_pointer_ref(self,c): + if c: + return c.get_m() + else: + return -7 + +a = Derived(False) +b = Derived(True) + +assert call_ret_c_shared_ptr(a) == 1 +assert call_ret_c_shared_ptr(b) == -1 +assert call_ret_c_by_value(a) == 1 + +assert call_take_c_by_value(a) == 5 +assert call_take_c_by_ref(a) == 6 +assert call_take_c_by_pointer(a) == 7 +assert call_take_c_by_pointer_ref(a) == 8 +assert call_take_c_shared_ptr_by_value(a) == 9 +assert call_take_c_shared_ptr_by_ref(a) == 10 +assert call_take_c_shared_ptr_by_pointer(a) == 11 +assert call_take_c_shared_ptr_by_pointer_ref(a) == 12 + +assert call_take_c_by_pointer_with_null(a) == -2 +assert call_take_c_by_pointer_ref_with_null(a) == -3 +assert call_take_c_shared_ptr_by_value_with_null(a) == -4 +assert call_take_c_shared_ptr_by_ref_with_null(a) == -5 +assert call_take_c_shared_ptr_by_pointer_with_null(a) == -6 +assert call_take_c_shared_ptr_by_pointer_ref_with_null(a) == -7 diff --git a/Examples/test-suite/python/li_carrays_cpp_runme.py b/Examples/test-suite/python/li_carrays_cpp_runme.py index 54d79aa46..112cd0015 100644 --- a/Examples/test-suite/python/li_carrays_cpp_runme.py +++ b/Examples/test-suite/python/li_carrays_cpp_runme.py @@ -7,3 +7,16 @@ d[5] = d[0] + 3 if d[5] + d[0] != 17: raise RuntimeError + +shorts = shortArray(5) + +sum = sum_array(shorts) +if sum != 0: + raise RuntimeError("incorrect zero sum, got: " + str(sum)) + +for i in range(5): + shorts[i] = i + +sum = sum_array(shorts) +if sum != 0+1+2+3+4: + raise RuntimeError("incorrect sum, got: " + str(sum)) diff --git a/Examples/test-suite/python/li_carrays_runme.py b/Examples/test-suite/python/li_carrays_runme.py index ad48eab61..90e03a5f4 100644 --- a/Examples/test-suite/python/li_carrays_runme.py +++ b/Examples/test-suite/python/li_carrays_runme.py @@ -7,3 +7,16 @@ d[5] = d[0] + 3 if d[5] + d[0] != 17: raise RuntimeError + +shorts = shortArray(5) + +sum = sum_array(shorts) +if sum != 0: + raise RuntimeError("incorrect zero sum, got: " + str(sum)) + +for i in range(5): + shorts[i] = i + +sum = sum_array(shorts) +if sum != 0+1+2+3+4: + raise RuntimeError("incorrect sum, got: " + str(sum)) diff --git a/Examples/test-suite/python/li_cpointer_cpp_runme.py b/Examples/test-suite/python/li_cpointer_cpp_runme.py index c49e9fc28..c763b85b8 100644 --- a/Examples/test-suite/python/li_cpointer_cpp_runme.py +++ b/Examples/test-suite/python/li_cpointer_cpp_runme.py @@ -2,6 +2,10 @@ from li_cpointer_cpp import * p = new_intp() + +if intp_value(p) != 0: + raise RuntimeError("not initialized") + intp_assign(p, 3) if intp_value(p) != 3: diff --git a/Examples/test-suite/python/li_cpointer_runme.py b/Examples/test-suite/python/li_cpointer_runme.py index 1565069cf..f0ec99060 100644 --- a/Examples/test-suite/python/li_cpointer_runme.py +++ b/Examples/test-suite/python/li_cpointer_runme.py @@ -2,6 +2,10 @@ from li_cpointer import * p = new_intp() + +if intp_value(p) != 0: + raise RuntimeError("not initialized") + intp_assign(p, 3) if intp_value(p) != 3: diff --git a/Examples/test-suite/python/li_cstring_runme.py b/Examples/test-suite/python/li_cstring_runme.py index 55b51d1c7..b718f1352 100644 --- a/Examples/test-suite/python/li_cstring_runme.py +++ b/Examples/test-suite/python/li_cstring_runme.py @@ -7,7 +7,7 @@ if count("ab\0ab\0ab\0", 0) != 3: if test1() != "Hello World": raise RuntimeError -if test2() != " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_": +if test2() != " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_": raise RuntimeError if test3("hello") != "hello-suffix": @@ -18,14 +18,14 @@ if test4("hello") != "hello-suffix": print test4("hello") raise RuntimeError -if test5(4) != 'xxxx': +if test5(4) != "xxxx": raise RuntimeError -if test6(10) != 'xxxxx': +if test6(10) != "xxxxx": raise RuntimeError if test7() != "Hello world!": raise RuntimeError -if test8() != " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_": +if test8() != " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_": raise RuntimeError diff --git a/Examples/test-suite/python/li_cwstring_runme.py b/Examples/test-suite/python/li_cwstring_runme.py index aaa5b6e62..5dd7b9b20 100644 --- a/Examples/test-suite/python/li_cwstring_runme.py +++ b/Examples/test-suite/python/li_cwstring_runme.py @@ -6,7 +6,7 @@ if count(u"ab\0ab\0ab\0", 0) != 3: if test1() != u"Hello World": raise RuntimeError -if test2() != u" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_": +if test2() != u" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_": raise RuntimeError if test3("hello") != u"hello-suffix": @@ -15,14 +15,14 @@ if test3("hello") != u"hello-suffix": if test4("hello") != u"hello-suffix": raise RuntimeError -if test5(4) != u'xxxx': +if test5(4) != u"xxxx": raise RuntimeError -if test6(10) != u'xxxxx': +if test6(10) != u"xxxxx": raise RuntimeError if test7() != u"Hello world!": raise RuntimeError -if test8() != u" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_": +if test8() != u" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_": raise RuntimeError diff --git a/Examples/test-suite/python/li_std_containers_int_runme.py b/Examples/test-suite/python/li_std_containers_int_runme.py index c7d262f60..941838a5f 100644 --- a/Examples/test-suite/python/li_std_containers_int_runme.py +++ b/Examples/test-suite/python/li_std_containers_int_runme.py @@ -84,16 +84,11 @@ def container_insert_step(i, j, step, newval): except IndexError, e: il_error = e - # Python 2.6 contains bug fixes in extended slicing syntax: - # http://docs.python.org/2/whatsnew/2.6.html - skip_check = ps_error != None and( - iv_error == il_error == None) and step > 0 and (sys.version_info[0:2] < (2, 6)) - if not(skip_check): - if not((type(ps_error) == type(iv_error)) and (type(ps_error) == type(il_error))): - raise RuntimeError, "ValueError exception not consistently thrown: " + \ - str(ps_error) + " " + str(iv_error) + " " + str(il_error) + if not((type(ps_error) == type(iv_error)) and (type(ps_error) == type(il_error))): + raise RuntimeError, "ValueError exception not consistently thrown: " + \ + str(ps_error) + " " + str(iv_error) + " " + str(il_error) - compare_containers(ps, iv, il) + compare_containers(ps, iv, il) # Check std::vector and std::list delete behaves same as Python list diff --git a/Examples/test-suite/python/li_std_map_runme.py b/Examples/test-suite/python/li_std_map_runme.py index af3e1d989..ac214dd45 100644 --- a/Examples/test-suite/python/li_std_map_runme.py +++ b/Examples/test-suite/python/li_std_map_runme.py @@ -50,3 +50,32 @@ mii[1] = 2 if mii[1] != 2: raise RuntimeError + +if mii.keys() != [1]: + raise RuntimeError("keys") +if mii.values() != [2]: + raise RuntimeError("values") +if mii.items() != [(1, 2)]: + raise RuntimeError("items") + +if [k for k in mii] != [1]: + raise RuntimeError("iteration") + +if [i for i in mii.iterkeys()] != [1]: + raise RuntimeError("iterkeys") +if [i for i in mii.itervalues()] != [2]: + raise RuntimeError("itervalues") +if [i for i in mii.iteritems()] != [(1, 2)]: + raise RuntimeError("iteritems") + + +slmap = li_std_map.StringLengthNumberMap() +li_std_map.populate(slmap) + +keys = " ".join([k for k in slmap.keys()]) +if keys != "a aa zzz xxxx aaaaa": + raise RuntimeError("Keys are wrong or in wrong order: " + keys) + +values = " ".join([str(v) for v in slmap.values()]) +if values != "1 2 3 4 5": + raise RuntimeError("Values are wrong or in wrong order: " + values) diff --git a/Examples/test-suite/python/li_std_set_runme.py b/Examples/test-suite/python/li_std_set_runme.py index ad3c6d881..5e5b72442 100644 --- a/Examples/test-suite/python/li_std_set_runme.py +++ b/Examples/test-suite/python/li_std_set_runme.py @@ -54,6 +54,8 @@ if i.next() != 2: if i.next() != 3: raise RuntimeError +if si[0] != 1: + raise RuntimeError i = s.begin() i.next() @@ -88,5 +90,5 @@ sum = () for i in s: sum = sum + (i,) -if (len(sum) != 3 or (not 1 in sum) or (not 'hello' in sum) or (not (1, 2) in sum)): +if (len(sum) != 3 or (not 1 in sum) or (not "hello" in sum) or (not (1, 2) in sum)): raise RuntimeError diff --git a/Examples/test-suite/python/li_std_string_extra_runme.py b/Examples/test-suite/python/li_std_string_extra_runme.py index b65f0774a..087d92b19 100644 --- a/Examples/test-suite/python/li_std_string_extra_runme.py +++ b/Examples/test-suite/python/li_std_string_extra_runme.py @@ -19,7 +19,7 @@ if li_std_string_extra.test_const_reference(x) != x: s = li_std_string_extra.string("he") #s += "ll" -# s.append('o') +# s.append("o") s = s + "llo" if s != x: @@ -87,6 +87,28 @@ if li_std_string_extra.test_value_basic2(x) != x: if li_std_string_extra.test_value_basic3(x) != x: raise RuntimeError, "bad string mapping" +if li_std_string_extra.test_value_basic_overload(x) != x: + raise RuntimeError, "bad overload string" + +if li_std_string_extra.test_value_basic_overload(123) != "int": + raise RuntimeError, "bad overload int" + +try: + li_std_string_extra.test_value_basic_overload([x]) + raise RuntimeError, "should throw TypeError" +except TypeError as e: + if str(e).find("Possible C/C++ prototypes are:") == -1: + raise RuntimeError("Incorrect error message text:\n{}".format(e)) + pass + +try: + li_std_string_extra.test_value_basic_overload([123]) + raise RuntimeError, "should throw TypeError" +except TypeError as e: + if str(e).find("Possible C/C++ prototypes are:") == -1: + raise RuntimeError("Incorrect error message text:\n{}".format(e)) + pass + # Global variables s = "initial string" if li_std_string_extra.cvar.GlobalString2 != "global string 2": diff --git a/Examples/test-suite/python/li_std_vector_back_reference_runme.py b/Examples/test-suite/python/li_std_vector_back_reference_runme.py new file mode 100644 index 000000000..cec9e8cc4 --- /dev/null +++ b/Examples/test-suite/python/li_std_vector_back_reference_runme.py @@ -0,0 +1,10 @@ +from li_std_vector_back_reference import * + +def first_element(): + v = VectorWheel((Wheel(11), Wheel(22))) + # v will be deleted after exit from this method + return v[0] + +size = first_element().size +if size != 11: + raise RuntimeError("Back reference not working {}".format(size)) diff --git a/Examples/test-suite/python/li_std_vector_extra_runme.py b/Examples/test-suite/python/li_std_vector_extra_runme.py index d541de6db..59e729a27 100644 --- a/Examples/test-suite/python/li_std_vector_extra_runme.py +++ b/Examples/test-suite/python/li_std_vector_extra_runme.py @@ -91,7 +91,7 @@ if v.size() != 0: v = vecStr(["hello ", "world"]) -if v[0] != 'hello world': +if v[0] != "hello world": raise RuntimeError, "bad std::string+std::vector" @@ -173,3 +173,11 @@ if extractConstShort(vcs[0]) != 111: if extractConstShort(vcs[1]) != 222: raise RuntimeError + +for p in vcs[0:1]: + if extractConstShort2(p) != 111: + raise RuntimeError + +for p in vcs[1:2]: + if extractConstShort2(p) != 222: + raise RuntimeError diff --git a/Examples/test-suite/python/li_std_vector_ptr_runme.py b/Examples/test-suite/python/li_std_vector_ptr_runme.py index b49cdb4e9..875d1c9c9 100644 --- a/Examples/test-suite/python/li_std_vector_ptr_runme.py +++ b/Examples/test-suite/python/li_std_vector_ptr_runme.py @@ -4,12 +4,20 @@ def check(val1, val2): if val1 != val2: raise RuntimeError("Values are not the same %s %s" % (val1, val2)) ip1 = makeIntPtr(11) -ip2 = makeIntPtr(22) +ip2 = makeIntPtr2(22) vi = IntPtrVector((ip1, ip2)) check(getValueFromVector(vi, 0), 11) check(getValueFromVector(vi, 1), 22) +check(getIntValue(vi[0]), 11) +check(getIntValue(vi[1]), 22) +check(getIntValue2(vi[0]), 11) +check(getIntValue2(vi[1]), 22) + +ipp = makeIntPtrPtr(vi[0]) +check(getIntValue3(ipp), 11) # Note: getIntValue3 takes int** + vA = APtrVector([makeA(33), makeA(34)]) check(getVectorValueA(vA, 0), 33) @@ -36,3 +44,21 @@ try: raise RuntimeError("missed exception") except TypeError: pass + +b111 = makeB(111) +bNones = BPtrVector([None, b111, None]) + +bCount = 0 +noneCount = 0 +for b in bNones: + if b == None: + noneCount = noneCount + 1 + else: + if b.val != 111: + raise RuntimeError("b.val is wrong") + bCount = bCount + 1 + +if bCount != 1: + raise RuntimeError("bCount wrong") +if noneCount != 2: + raise RuntimeError("noneCount wrong") diff --git a/Examples/test-suite/python/li_std_vector_runme.py b/Examples/test-suite/python/li_std_vector_runme.py index 68a6d0348..71460519d 100644 --- a/Examples/test-suite/python/li_std_vector_runme.py +++ b/Examples/test-suite/python/li_std_vector_runme.py @@ -2,3 +2,9 @@ from li_std_vector import * if typedef_test(101) != 101: raise RuntimeError + +try: + sv = StructVector([None, None]) + raise RuntimeError("Using None should result in a TypeError") +except TypeError: + pass diff --git a/Examples/test-suite/python/li_std_wstring_inherit_runme.py b/Examples/test-suite/python/li_std_wstring_inherit_runme.py new file mode 100644 index 000000000..558914e7e --- /dev/null +++ b/Examples/test-suite/python/li_std_wstring_inherit_runme.py @@ -0,0 +1,45 @@ +import li_std_wstring_inherit +import sys + +x = u"hello" + +s = li_std_wstring_inherit.wstring(u"he") +s = s + u"llo" + +if s != x: + print s, x + raise RuntimeError("bad string mapping") + +if s[1:4] != x[1:4]: + raise RuntimeError("bad string mapping") + +a = li_std_wstring_inherit.A(s) +b = li_std_wstring_inherit.wstring(" world") + +if a + b != "hello world": + raise RuntimeError("bad string mapping") + +if a + " world" != "hello world": + raise RuntimeError("bad string mapping") + +# This is expected to fail if -builtin is used +# Reverse operators not supported in builtin types +if not li_std_wstring_inherit.is_python_builtin(): + if "hello" + b != "hello world": + raise RuntimeError("bad string mapping") + + c = "hello" + b + if c.find_last_of("l") != 9: + raise RuntimeError("bad string mapping") + +b = li_std_wstring_inherit.B("hi") + +b.name = li_std_wstring_inherit.wstring(u"hello") +if b.name != "hello": + raise RuntimeError("bad string mapping") + + +b.a = li_std_wstring_inherit.A("hello") +if b.a != u"hello": + raise RuntimeError("bad string mapping") + diff --git a/Examples/test-suite/python/li_std_wstring_runme.py b/Examples/test-suite/python/li_std_wstring_runme.py index e93196b80..c6210e2de 100644 --- a/Examples/test-suite/python/li_std_wstring_runme.py +++ b/Examples/test-suite/python/li_std_wstring_runme.py @@ -1,83 +1,79 @@ import li_std_wstring +import sys -x = u"h" +def check_equal(a, b): + if a != b: + raise RuntimeError("failed {} {}".format(a, b)) -if li_std_wstring.test_wcvalue(x) != x: - print li_std_wstring.test_wcvalue(x) - raise RuntimeError("bad string mapping") +h = u"h" +check_equal(li_std_wstring.test_wcvalue(h), h) -x = u"hello" -if li_std_wstring.test_ccvalue(x) != x: - raise RuntimeError("bad string mapping") +x = u"abc" +check_equal(li_std_wstring.test_ccvalue(x), x) +check_equal(li_std_wstring.test_cvalue(x), x) -if li_std_wstring.test_cvalue(x) != x: - raise RuntimeError("bad string mapping") +check_equal(li_std_wstring.test_wchar_overload(x), x) +check_equal(li_std_wstring.test_wchar_overload(), None) -if li_std_wstring.test_wchar_overload(x) != x: - raise RuntimeError("bad string mapping") +li_std_wstring.test_pointer(None) +li_std_wstring.test_const_pointer(None) -if li_std_wstring.test_wchar_overload("not unicode") != "not unicode": - raise RuntimeError("bad string mapping") +try: + li_std_wstring.test_value(None) + raise RuntimeError("NULL check failed") +except TypeError as e: + pass -if li_std_wstring.test_value(x) != x: - print x, li_std_wstring.test_value(x) - raise RuntimeError("bad string mapping") +try: + li_std_wstring.test_reference(None) + raise RuntimeError("NULL check failed") +except ValueError as e: + if "invalid null reference" not in str(e): + raise RuntimeError("Missing text {}".format(e)) +try: + li_std_wstring.test_const_reference(None) + raise RuntimeError("NULL check failed") +except ValueError as e: + if "invalid null reference" not in str(e): + raise RuntimeError("Missing text {}".format(e)) -if li_std_wstring.test_const_reference(x) != x: - raise RuntimeError("bad string mapping") +x = "hello" +check_equal(li_std_wstring.test_const_reference(x), x) +s = "abc" +if not li_std_wstring.test_equal_abc(s): + raise RuntimeError("Not equal {}".format(s)) -s = li_std_wstring.wstring(u"he") -s = s + u"llo" +try: + li_std_wstring.test_throw +except RuntimeError as e: + check_equal(e.message, "throwing test_throw") -if s != x: - print s, x - raise RuntimeError("bad string mapping") +x = "abc\0def" +check_equal(li_std_wstring.test_value(x), x) +check_equal(li_std_wstring.test_ccvalue(x), "abc") +check_equal(li_std_wstring.test_wchar_overload(x), "abc") -if s[1:4] != x[1:4]: - raise RuntimeError("bad string mapping") +################### Python specific -if li_std_wstring.test_value(s) != x: - raise RuntimeError("bad string mapping") - -if li_std_wstring.test_const_reference(s) != x: - raise RuntimeError("bad string mapping") - -a = li_std_wstring.A(s) - -if li_std_wstring.test_value(a) != x: - raise RuntimeError("bad string mapping") - -if li_std_wstring.test_const_reference(a) != x: - raise RuntimeError("bad string mapping") - -b = li_std_wstring.wstring(" world") - -if a + b != "hello world": - raise RuntimeError("bad string mapping") - -if a + " world" != "hello world": - raise RuntimeError("bad string mapping") - -# This is expected to fail if -builtin is used -# Reverse operators not supported in builtin types -if not li_std_wstring.is_python_builtin(): - if "hello" + b != "hello world": +# Byte strings only converted in Python 2 +if sys.version_info[0:2] < (3, 0): + x = b"hello there" + if li_std_wstring.test_value(x) != x: raise RuntimeError("bad string mapping") - c = "hello" + b - if c.find_last_of("l") != 9: - raise RuntimeError("bad string mapping") +# Invalid utf-8 in a byte string fails in all versions +x = b"h\xe9llo" +try: + li_std_wstring.test_value(x) + raise RuntimeError("TypeError not thrown") +except TypeError: + pass -s = "hello world" - -b = li_std_wstring.B("hi") - -b.name = li_std_wstring.wstring(u"hello") -if b.name != "hello": - raise RuntimeError("bad string mapping") - - -b.a = li_std_wstring.A("hello") -if b.a != u"hello": - raise RuntimeError("bad string mapping") +# Check surrogateescape +if sys.version_info[0:2] > (3, 1): + x = u"h\udce9llo" # surrogate escaped representation of C char*: "h\xe9llo" + if li_std_wstring.non_utf8_c_str() != x: + raise RuntimeError("surrogateescape not working") + if li_std_wstring.size_wstring(x) != 5 and len(x) != 5: + raise RuntimeError("Unexpected length") diff --git a/Examples/test-suite/python/member_pointer_const_runme.py b/Examples/test-suite/python/member_pointer_const_runme.py new file mode 100644 index 000000000..ad6c2df99 --- /dev/null +++ b/Examples/test-suite/python/member_pointer_const_runme.py @@ -0,0 +1,51 @@ +# Example using pointers to member functions + +from member_pointer_const import * + + +def check(what, expected, actual): + if expected != actual: + raise RuntimeError( + "Failed: ", what, " Expected: ", expected, " Actual: ", actual) + +# Get the pointers + +area_pt = areapt() +perim_pt = perimeterpt() + +# Create some objects + +s = Square(10) + +# Do some calculations + +check("Square area ", 100.0, do_op(s, area_pt)) +check("Square perim", 40.0, do_op(s, perim_pt)) + +memberPtr = cvar.areavar +memberPtr = cvar.perimetervar + +# Try the variables +check("Square area ", 100.0, do_op(s, cvar.areavar)) +check("Square perim", 40.0, do_op(s, cvar.perimetervar)) + +# Modify one of the variables +cvar.areavar = perim_pt + +check("Square perimeter", 40.0, do_op(s, cvar.areavar)) + +# Try the constants + +memberPtr = AREAPT +memberPtr = PERIMPT +memberPtr = NULLPT + +check("Square area ", 100.0, do_op(s, AREAPT)) +check("Square perim", 40.0, do_op(s, PERIMPT)) + +# Typedefs +check("Square perim", 40.0, do_op_td(s, perim_pt)); + +check("Add by value", 3, call1(ADD_BY_VALUE, 1, 2)) +#check("Add by pointer", 7, call2(ADD_BY_POINTER, 3, 4)) +#check("Add by reference", 11, call3(ADD_BY_REFERENCE, 5, 6)) diff --git a/Examples/test-suite/python/member_pointer_runme.py b/Examples/test-suite/python/member_pointer_runme.py index 5ae7ab9a4..f6f165863 100644 --- a/Examples/test-suite/python/member_pointer_runme.py +++ b/Examples/test-suite/python/member_pointer_runme.py @@ -43,6 +43,9 @@ memberPtr = NULLPT check("Square area ", 100.0, do_op(s, AREAPT)) check("Square perim", 40.0, do_op(s, PERIMPT)) +# Typedefs +check("Square perim", 40.0, do_op_td(s, perim_pt)); + check("Add by value", 3, call1(ADD_BY_VALUE, 1, 2)) check("Add by pointer", 7, call2(ADD_BY_POINTER, 3, 4)) check("Add by reference", 11, call3(ADD_BY_REFERENCE, 5, 6)) diff --git a/Examples/test-suite/python/namespace_class_runme.py b/Examples/test-suite/python/namespace_class_runme.py index e0bd3ca09..aa5165562 100644 --- a/Examples/test-suite/python/namespace_class_runme.py +++ b/Examples/test-suite/python/namespace_class_runme.py @@ -1,9 +1,5 @@ from namespace_class import * - -def is_new_style_class(cls): - return hasattr(cls, "__class__") - try: p = Private1() error = 1 @@ -22,10 +18,7 @@ except: if (error): raise RuntimeError, "Private2 is private" -if is_new_style_class(EulerT3D): - EulerT3D.toFrame(1, 1, 1) -else: - EulerT3D().toFrame(1, 1, 1) +EulerT3D.toFrame(1, 1, 1) b = BooT_i() b = BooT_H() @@ -40,7 +33,6 @@ f.moo(1) f = FooT_H() f.foo(Hi) -if is_new_style_class(FooT_H): - f_type = str(type(f)) - if f_type.find("'namespace_class.FooT_H'") == -1: - raise RuntimeError("Incorrect type: " + f_type) +f_type = str(type(f)) +if f_type.find("'namespace_class.FooT_H'") == -1: + raise RuntimeError("Incorrect type: " + f_type) diff --git a/Examples/test-suite/python/nested_in_template_runme.py b/Examples/test-suite/python/nested_in_template_runme.py new file mode 100644 index 000000000..69afd1604 --- /dev/null +++ b/Examples/test-suite/python/nested_in_template_runme.py @@ -0,0 +1,5 @@ +from nested_in_template import * + +cd = ConcreteDerived(88) +if cd.m_value != 88: + raise RuntimeError("ConcreteDerived not created correctly") diff --git a/Examples/test-suite/python/nested_runme.py b/Examples/test-suite/python/nested_runme.py new file mode 100644 index 000000000..0e839e64b --- /dev/null +++ b/Examples/test-suite/python/nested_runme.py @@ -0,0 +1,20 @@ +from nested import * + +def check(a, b): + if a != b: + raise RuntimeError("Problem: {} != {}".format(a, b)) +xx = x_t() +yy = y_t() +aa = a_t() +bb = b_t() +cc = c_t() +dd = d_t() + +set_union_values(100, xx, yy, aa, bb, cc, dd) + +check(xx.duplicate_p.x, 100) +check(yy.duplicate_p.y, 101) +check(aa.duplicate_p.a, 102) +check(bb.duplicate_p.b, 103) +check(cc.duplicate_p.c, 104) +check(dd.duplicate_p.d, 105) diff --git a/Examples/test-suite/python/operator_overload_runme.py b/Examples/test-suite/python/operator_overload_runme.py index cf4277f35..31c49058e 100644 --- a/Examples/test-suite/python/operator_overload_runme.py +++ b/Examples/test-suite/python/operator_overload_runme.py @@ -75,3 +75,10 @@ if not -a==a: if not -b==Op(-5): raise RuntimeError("-b==Op(-5)") +# test functors +if not b()==5: + raise RuntimeError("functor") +if not b(1)==6: + raise RuntimeError("functor") +if not b(1, 2)==8: + raise RuntimeError("functor") diff --git a/Examples/test-suite/python/overload_complicated_runme.py b/Examples/test-suite/python/overload_complicated_runme.py index 9c039a0a5..2593c4f16 100644 --- a/Examples/test-suite/python/overload_complicated_runme.py +++ b/Examples/test-suite/python/overload_complicated_runme.py @@ -5,11 +5,11 @@ pInt = None # Check the correct constructors are available p = Pop(pInt) -p = Pop(pInt, 0) +p = Pop(pInt, False) # Check overloaded in const only and pointers/references which target # languages cannot disambiguate -if p.hip(0) != 701: +if p.hip(False) != 701: raise RuntimeError, "Test 1 failed" if p.hip(pInt) != 702: @@ -19,14 +19,14 @@ if p.hip(pInt) != 702: if p.hop(pInt) != 805: raise RuntimeError, "Test 3 failed" -if p.hop(0) != 801: +if p.hop(False) != 801: raise RuntimeError, "Test 4 failed" # Few more variations and order shuffled -if p.pop(0) != 901: +if p.pop(False) != 901: raise RuntimeError, "Test 5 failed" -if p.pop(pInt) != 902: +if p.pop(pInt) != 904: raise RuntimeError, "Test 6 failed" if p.pop() != 905: @@ -36,11 +36,11 @@ if p.pop() != 905: if p.bop(pInt) != 1001: raise RuntimeError, "Test 8 failed" -if p.bip(pInt) != 2001: +if p.bip(pInt) != 2002: raise RuntimeError, "Test 9 failed" # Globals -if muzak(0) != 3001: +if muzak(False) != 3001: raise RuntimeError, "Test 10 failed" if muzak(pInt) != 3002: diff --git a/Examples/test-suite/python/overload_null_runme.py b/Examples/test-suite/python/overload_null_runme.py new file mode 100644 index 000000000..a34524255 --- /dev/null +++ b/Examples/test-suite/python/overload_null_runme.py @@ -0,0 +1,44 @@ +from overload_null import * + +def check(a, b): + if a != b: + raise RuntimeError(str(a) + " does not equal " + str(b)) + +o = Overload() +x = X() + +check(1, o.byval1(x)) +check(2, o.byval1(None)) + +check(3, o.byval2(None)) +check(4, o.byval2(x)) + +check(5, o.byref1(x)) +check(6, o.byref1(None)) + +check(7, o.byref2(None)) +check(8, o.byref2(x)) + +check(9, o.byconstref1(x)) +check(10, o.byconstref1(None)) + +check(11, o.byconstref2(None)) +check(12, o.byconstref2(x)) + +# const pointer references +check(13, o.byval1cpr(x)) +check(14, o.byval1cpr(None)) + +check(15, o.byval2cpr(None)) +check(16, o.byval2cpr(x)) + +# forward class declaration +check(17, o.byval1forwardptr(x)) +check(18, o.byval1forwardptr(None)) + +check(19, o.byval2forwardptr(None)) +check(20, o.byval2forwardptr(x)) + +check(21, o.byval1forwardref(x)) + +check(22, o.byval2forwardref(x)) diff --git a/Examples/test-suite/python/overload_template_fast_runme.py b/Examples/test-suite/python/overload_template_fast_runme.py index 95349a9b1..ca3cac9b5 100644 --- a/Examples/test-suite/python/overload_template_fast_runme.py +++ b/Examples/test-suite/python/overload_template_fast_runme.py @@ -1,9 +1,5 @@ from overload_template_fast import * - -def is_new_style_class(cls): - return hasattr(cls, "__class__") - f = foo() a = maximum(3, 4) @@ -145,9 +141,6 @@ if (nsoverload() != 1050): raise RuntimeError, ("nsoverload(const char *)") -if is_new_style_class(A): - A.foo(1) -else: - A_foo(1) +A.foo(1) b = B() b.foo(1) diff --git a/Examples/test-suite/python/preproc_gcc_output_runme.py b/Examples/test-suite/python/preproc_gcc_output_runme.py new file mode 100644 index 000000000..66ff7d21a --- /dev/null +++ b/Examples/test-suite/python/preproc_gcc_output_runme.py @@ -0,0 +1,5 @@ +import preproc_gcc_output + +preproc_gcc_output.header1_function_a(99) +preproc_gcc_output.header1_function_b(99) +preproc_gcc_output.header2_function(99) diff --git a/Examples/test-suite/python/preproc_runme.py b/Examples/test-suite/python/preproc_runme.py index 99a6d0307..071362bc3 100644 --- a/Examples/test-suite/python/preproc_runme.py +++ b/Examples/test-suite/python/preproc_runme.py @@ -14,3 +14,6 @@ if 2 * preproc.one != preproc.two: if preproc.methodX(99) != 199: raise RuntimeError + +t1 = preproc.tcxMessageTest() +t2 = preproc.tcxMessageBug() diff --git a/Examples/test-suite/python/primitive_ref_runme.py b/Examples/test-suite/python/primitive_ref_runme.py index f3a640389..2f1a5144c 100644 --- a/Examples/test-suite/python/primitive_ref_runme.py +++ b/Examples/test-suite/python/primitive_ref_runme.py @@ -33,7 +33,7 @@ if ref_double(3.5) != 3.5: if ref_bool(True) != True: raise RuntimeError -if ref_char('x') != 'x': +if ref_char("x") != "x": raise RuntimeError if ref_over(0) != 0: diff --git a/Examples/test-suite/python/primitive_types_runme.py b/Examples/test-suite/python/primitive_types_runme.py index b2060a028..04588ddf2 100644 --- a/Examples/test-suite/python/primitive_types_runme.py +++ b/Examples/test-suite/python/primitive_types_runme.py @@ -227,7 +227,7 @@ t.var_paramc = sct_paramc t.v_check() # this value contains a '0' char! -if def_namet != 'hola': +if def_namet != "hola": print "bad namet", def_namet raise RuntimeError @@ -236,54 +236,54 @@ if t.var_namet != def_namet: print "bad namet", t.var_namet, def_namet raise RuntimeError -t.var_namet = 'hola' +t.var_namet = "hola" -if t.var_namet != 'hola': +if t.var_namet != "hola": print "bad namet", t.var_namet raise RuntimeError -t.var_namet = 'hol' +t.var_namet = "hol" -if t.var_namet != 'hol': - # if t.var_namet != 'hol\0\0': +if t.var_namet != "hol": + # if t.var_namet != "hol\0\0": print "bad namet", t.var_namet raise RuntimeError -cvar.var_char = '\0' -if cvar.var_char != '\0': +cvar.var_char = "\0" +if cvar.var_char != "\0": raise RuntimeError, "bad char '0' case" cvar.var_char = 0 -if cvar.var_char != '\0': +if cvar.var_char != "\0": raise RuntimeError, "bad char '0' case" -cvar.var_namet = '\0' -# if cvar.var_namet != '\0\0\0\0\0': -if cvar.var_namet != '': - print 'hola', '', cvar.var_namet +cvar.var_namet = "\0" +# if cvar.var_namet != "\0\0\0\0\0": +if cvar.var_namet != "": + print "hola", "", cvar.var_namet raise RuntimeError, "bad char '\0' case" -cvar.var_namet = '' -# if cvar.var_namet != '\0\0\0\0\0': -if cvar.var_namet != '': +cvar.var_namet = "" +# if cvar.var_namet != "\0\0\0\0\0": +if cvar.var_namet != "": raise RuntimeError, "bad char empty case" cvar.var_pchar = None if cvar.var_pchar != None: raise RuntimeError, "bad None case" -cvar.var_pchar = '' -if cvar.var_pchar != '': - print '%c' % (cvar.var_pchar[0],) +cvar.var_pchar = "" +if cvar.var_pchar != "": + print "%c" % (cvar.var_pchar[0],) raise RuntimeError, "bad char empty case" cvar.var_pcharc = None if cvar.var_pcharc != None: raise RuntimeError, "bad None case" -cvar.var_pcharc = '' -if cvar.var_pcharc != '': +cvar.var_pcharc = "" +if cvar.var_pcharc != "": raise RuntimeError, "bad char empty case" @@ -291,10 +291,10 @@ if cvar.var_pcharc != '': # creating a raw char* # pc = new_pchar(5) -pchar_setitem(pc, 0, 'h') -pchar_setitem(pc, 1, 'o') -pchar_setitem(pc, 2, 'l') -pchar_setitem(pc, 3, 'a') +pchar_setitem(pc, 0, "h") +pchar_setitem(pc, 1, "o") +pchar_setitem(pc, 2, "l") +pchar_setitem(pc, 3, "a") pchar_setitem(pc, 4, 0) @@ -331,7 +331,7 @@ if error: try: error = 0 a = t.var_char - t.var_char = '23' + t.var_char = "23" error = 1 except TypeError: if a != t.var_char: @@ -393,7 +393,7 @@ if error: try: error = 0 a = t.var_namet - t.var_namet = '123456' + t.var_namet = "123456" error = 1 except TypeError: if a != t.var_namet: @@ -410,11 +410,11 @@ if t.var_namet != t2.var_namet: raise RuntimeError, "bad SWIGTYPE* typemap" -if cvar.fixsize != 'ho\0la\0\0\0': +if cvar.fixsize != "ho\0la\0\0\0": raise RuntimeError, "bad FIXSIZE typemap" -cvar.fixsize = 'ho' -if cvar.fixsize != 'ho\0\0\0\0\0\0': +cvar.fixsize = "ho" +if cvar.fixsize != "ho\0\0\0\0\0\0": raise RuntimeError, "bad FIXSIZE typemap" @@ -487,26 +487,26 @@ def checkType(t, e, val, delta): """t = Test object, e = type name (e.g. ulong), val = max or min allowed value, delta = +1 for max, -1 for min""" error = 0 # Set the extreme valid value for var_* - setattr(t, 'var_' + e, val) + setattr(t, "var_" + e, val) # Make sure it was set properly and works properly in the val_* and ref_* methods - if getattr(t, 'var_' + e) != val or getattr(t, 'val_' + e)(val) != val or getattr(t, 'ref_' + e)(val) != val: + if getattr(t, "var_" + e) != val or getattr(t, "val_" + e)(val) != val or getattr(t, "ref_" + e)(val) != val: error = 1 # Make sure setting a more extreme value fails without changing the value try: - a = getattr(t, 'var_' + e) - setattr(t, 'var_' + e, val + delta) + a = getattr(t, "var_" + e) + setattr(t, "var_" + e, val + delta) error = 1 except OverflowError: - if a != getattr(t, 'var_' + e): + if a != getattr(t, "var_" + e): error = 1 # Make sure the val_* and ref_* methods fail with a more extreme value try: - getattr(t, 'val_' + e)(val + delta) + getattr(t, "val_" + e)(val + delta) error = 1 except OverflowError: pass try: - getattr(t, 'ref_' + e)(val + delta) + getattr(t, "ref_" + e)(val + delta) error = 1 except OverflowError: pass @@ -518,16 +518,16 @@ def checkFull(t, e, maxval, minval): checkType(t, e, maxval, 1) checkType(t, e, minval, -1) -checkFull(t, 'llong', maxllong, minllong) -checkFull(t, 'long', maxlong, minlong) -checkFull(t, 'int', maxint, minint) -checkFull(t, 'short', maxshort, minshort) -checkFull(t, 'schar', maxchar, minchar) -checkFull(t, 'ullong', maxullong, 0) -checkFull(t, 'ulong', maxulong, 0) -checkFull(t, 'uint', maxuint, 0) -checkFull(t, 'ushort', maxushort, 0) -checkFull(t, 'uchar', maxuchar, 0) +checkFull(t, "llong", maxllong, minllong) +checkFull(t, "long", maxlong, minlong) +checkFull(t, "int", maxint, minint) +checkFull(t, "short", maxshort, minshort) +checkFull(t, "schar", maxchar, minchar) +checkFull(t, "ullong", maxullong, 0) +checkFull(t, "ulong", maxulong, 0) +checkFull(t, "uint", maxuint, 0) +checkFull(t, "ushort", maxushort, 0) +checkFull(t, "uchar", maxuchar, 0) def checkOverload(t, name, val, delta, prevval, limit): """ @@ -549,28 +549,23 @@ def checkOverload(t, name, val, delta, prevval, limit): if t.ovr_str(val + delta) == name: raise RuntimeError, "bad " + name + " typemap" if val == limit: - # Should raise NotImplementedError here since this is the largest integral type - raise RuntimeError, "bad " + name + " typemap" - except NotImplementedError: - # NotImplementedError is expected only if this is the most extreme type - if val != limit: + # Should raise TypeError here since this is the largest integral type raise RuntimeError, "bad " + name + " typemap" except TypeError: - # TypeError is raised instead if swig is run with -O or -fastdispatch if val != limit: raise RuntimeError, "bad " + name + " typemap" # Check that overloading works: uchar > schar > ushort > short > uint > int > ulong > long > ullong > llong -checkOverload(t, 'uchar', maxuchar, +1, 0, maxullong) -checkOverload(t, 'ushort', maxushort, +1, maxuchar, maxullong) -checkOverload(t, 'uint', maxuint, +1, maxushort, maxullong) -checkOverload(t, 'ulong', maxulong, +1, maxuint, maxullong) -checkOverload(t, 'ullong', maxullong, +1, maxulong, maxullong) -checkOverload(t, 'schar', minchar, -1, 0, minllong) -checkOverload(t, 'short', minshort, -1, minchar, minllong) -checkOverload(t, 'int', minint, -1, minshort, minllong) -checkOverload(t, 'long', minlong, -1, minint, minllong) -checkOverload(t, 'llong', minllong, -1, minlong, minllong) +checkOverload(t, "uchar", maxuchar, +1, 0, maxullong) +checkOverload(t, "ushort", maxushort, +1, maxuchar, maxullong) +checkOverload(t, "uint", maxuint, +1, maxushort, maxullong) +checkOverload(t, "ulong", maxulong, +1, maxuint, maxullong) +checkOverload(t, "ullong", maxullong, +1, maxulong, maxullong) +checkOverload(t, "schar", minchar, -1, 0, minllong) +checkOverload(t, "short", minshort, -1, minchar, minllong) +checkOverload(t, "int", minint, -1, minshort, minllong) +checkOverload(t, "long", minlong, -1, minint, minllong) +checkOverload(t, "llong", minllong, -1, minlong, minllong) # Make sure that large ints can be converted to doubles properly if val_double(sys.maxint + 1) != float(sys.maxint + 1): diff --git a/Examples/test-suite/python/python_abstractbase_runme3.py b/Examples/test-suite/python/python_abstractbase_runme3.py index 4fdc79935..9f99dcb54 100644 --- a/Examples/test-suite/python/python_abstractbase_runme3.py +++ b/Examples/test-suite/python/python_abstractbase_runme3.py @@ -1,5 +1,11 @@ +import sys + +# collections.abc requires Python 3.3+ +if sys.version_info[0:2] < (3, 3): + exit(0) + from python_abstractbase import * -from collections import * +import collections.abc # This is expected to fail with -builtin option # Builtin types can't inherit from pure-python abstract bases @@ -10,12 +16,16 @@ if is_python_builtin(): if not is_swig_py3: exit(0) -assert issubclass(Mapii, MutableMapping) -assert issubclass(Multimapii, MutableMapping) -assert issubclass(IntSet, MutableSet) -assert issubclass(IntMultiset, MutableSet) -assert issubclass(IntVector, MutableSequence) -assert issubclass(IntList, MutableSequence) +def check_issubclass(derived, base): + if not issubclass(derived, base): + raise RuntimeError("{} is not a subclass of {}".format(derived, base)) + +check_issubclass(Mapii, collections.abc.MutableMapping) +check_issubclass(Multimapii, collections.abc.MutableMapping) +check_issubclass(IntSet, collections.abc.MutableSet) +check_issubclass(IntMultiset, collections.abc.MutableSet) +check_issubclass(IntVector, collections.abc.MutableSequence) +check_issubclass(IntList, collections.abc.MutableSequence) mapii = Mapii() multimapii = Multimapii() diff --git a/Examples/test-suite/python/python_append_runme.py b/Examples/test-suite/python/python_append_runme.py index 6675f3509..eddda53ff 100644 --- a/Examples/test-suite/python/python_append_runme.py +++ b/Examples/test-suite/python/python_append_runme.py @@ -1,19 +1,13 @@ from python_append import * -def is_new_style_class(cls): - return hasattr(cls, "__class__") - # test not relevant for -builtin if is_python_builtin(): exit(0) t = Test() -t.func() -if is_new_style_class(Test): - t.static_func() -else: - Test_static_func() +t.funk() +t.static_func() if grabpath() != os.path.dirname(mypath): raise RuntimeError("grabpath failed") diff --git a/Examples/test-suite/python/python_builtin_runme.py b/Examples/test-suite/python/python_builtin_runme.py index 70990cbfd..26e757ca7 100644 --- a/Examples/test-suite/python/python_builtin_runme.py +++ b/Examples/test-suite/python/python_builtin_runme.py @@ -12,10 +12,14 @@ if is_python_builtin(): if h != h2: raise RuntimeError("default tp_hash not working") - # Test 1 for tp_hash + # Test 1a for tp_hash if hash(SimpleValue(222)) != 222: raise RuntimeError("tp_hash not working") + # Test 1b for tp_hash + if hash(SimpleValue2(333)) != 333: + raise RuntimeError("tp_hash not working") + # Test 2 for tp_hash try: # Was incorrectly raising: SystemError: error return without exception set @@ -79,3 +83,31 @@ if is_python_builtin(): if MyClass.less_than_counts != 6: raise RuntimeError("python:compare feature not working") +# Test 6 +sa = SimpleArray(5) +elements = [x for x in sa] +if elements != [0, 10, 20, 30, 40]: + raise RuntimeError("Iteration not working") +if len(sa) != 5: + raise RuntimeError("len not working") +for i in range(5): + if sa[i] != i*10: + raise RuntimeError("indexing not working") +subslice = sa[1:3] +elements = [x for x in subslice] +if elements != [10, 20]: + raise RuntimeError("slice not working") + +# Test 7 mapping to Python's pow +x = ANumber(2) +y = ANumber(4) +z = x ** y +if z.Value() != 16: + raise RuntimeError("x ** y wrong") +z = pow(x, y) +if z.Value() != 16: + raise RuntimeError("pow(x, y) wrong") +z = ANumber(9) +z = pow(x, y, z) +if z.Value() != 7: + raise RuntimeError("pow(x, y, z) wrong") diff --git a/Examples/test-suite/python/python_docstring_runme.py b/Examples/test-suite/python/python_docstring_runme.py index 0284ea0de..a601ecb54 100644 --- a/Examples/test-suite/python/python_docstring_runme.py +++ b/Examples/test-suite/python/python_docstring_runme.py @@ -9,7 +9,7 @@ def check(got, expected): raise RuntimeError("\n" + "Expected: " + str(expected_list) + "\n" + "Got : " + str(got_list)) # When getting docstrings, use inspect.getdoc(x) instead of x.__doc__ otherwise the different options -# such as -O, -builtin, -classic produce different initial indentation. +# such as -O and -builtin may produce different initial indentation. check(inspect.getdoc(DocStrings.docstring1), " line 1\n" diff --git a/Examples/test-suite/python/python_extranative_runme.py b/Examples/test-suite/python/python_extranative_runme.py new file mode 100644 index 000000000..7be13a7ee --- /dev/null +++ b/Examples/test-suite/python/python_extranative_runme.py @@ -0,0 +1,11 @@ +import python_extranative + +vs = python_extranative.make_vector_string() +if not isinstance(vs, python_extranative.VectorString): + # will be of type tuple if extranative not working + raise RuntimeError("Not of type VectorString") + +for s1, s2 in zip(vs, ["one", "two"]): + if s1 != s2: + raise RuntimeError("Mismatch: " + s1 + " " + s2) + diff --git a/Examples/test-suite/python/python_moduleimport_runme.py b/Examples/test-suite/python/python_moduleimport_runme.py new file mode 100644 index 000000000..cdb860730 --- /dev/null +++ b/Examples/test-suite/python/python_moduleimport_runme.py @@ -0,0 +1,7 @@ +import python_moduleimport + +if python_moduleimport.simple_function(99) != 99: + raise RuntimeError("simple_function") + +if python_moduleimport.extra_import_variable != "custom import of _python_moduleimport": + raise RuntimeError("custom import") diff --git a/Examples/test-suite/python/python_nondynamic_runme.py b/Examples/test-suite/python/python_nondynamic_runme.py index 6a430961e..fbb60ad36 100644 --- a/Examples/test-suite/python/python_nondynamic_runme.py +++ b/Examples/test-suite/python/python_nondynamic_runme.py @@ -1,21 +1,41 @@ import python_nondynamic +def is_python_modern(): + """Return True if SWIG is generating Python code using -modern. Works only if %python_nondynamic has been used.""" + return hasattr(python_nondynamic, "_swig_setattr_nondynamic_class_variable") + +def debug_print(s): + show_debug = False + if show_debug: + print(s) + aa = python_nondynamic.A() aa.a = 1 aa.b = 2 + +# Check values are really set +if python_nondynamic.retrieve_A_a(aa) != 1: raise RuntimeError("a not set correctly") +if python_nondynamic.retrieve_A_b(aa) != 2: raise RuntimeError("b not set correctly") + try: aa.c = 2 - err = 0 -except: - err = 1 - -if not err: - raise RuntimeError, "A is not static" + raise RuntimeError("A is not static") +except AttributeError as e: + debug_print(e) + pass +class PurePythonClass(object): + def __init__(self): + self.variables = dict() + def __set__(self, name, value): + self.variables[name] = value + pass class B(python_nondynamic.A): c = 4 + cc = PurePythonClass() + cc.nnn = "new attrib" def __init__(self): python_nondynamic.A.__init__(self) @@ -23,26 +43,66 @@ class B(python_nondynamic.A): pass bb = B() +bb.a = 4 +bb.b = 5 +# Check values are really set +if python_nondynamic.retrieve_A_a(bb) != 4: raise RuntimeError("a not set correctly") +if python_nondynamic.retrieve_A_b(bb) != 5: raise RuntimeError("b not set correctly") try: bb.c = 3 - err = 0 -except: - err = 1 - -if not err: - print "bb.c = %d" % bb.c - print "B.c = %d" % B.c - raise RuntimeError, "B.c class variable messes up nondynamic-ness of B" + print("bb.c = {}".format(bb.c)) + print("B.c = {}".format(B.c)) + raise RuntimeError("B.c class variable messes up nondynamic-ness of B") +except AttributeError as e: + debug_print(e) + pass try: bb.d = 2 - err = 0 -except: - err = 1 - -if not err: - raise RuntimeError, "B is not static" + raise RuntimeError("B is not static") +except AttributeError as e: + debug_print(e) + pass cc = python_nondynamic.C() cc.d = 3 + +# An inconsistency between builtin and (non-builtin/modern). +# Class variables cannot be set on builtin types, like other Python builtins, eg list.classvar=111 fails +if python_nondynamic.is_python_builtin(): + try: + python_nondynamic.C.classvar = 111 + raise RuntimeError("C should not allow static variables to be added when using builtin") + except AttributeError as e: + debug_print(e) + pass +else: + python_nondynamic.C.classvar = 111 + +if is_python_modern() and not python_nondynamic.is_python_builtin(): + # Not working with builtin or non-modern :( + try: + B.a = 10 + raise RuntimeError("B should not allow adding a class variable by setting it as an instance variable") + except AttributeError as e: + debug_print(e) + pass + + try: + python_nondynamic.A.a = 10 + raise RuntimeError("A should not allow adding a class variable by setting it as an instance variable") + except AttributeError as e: + debug_print(e) + pass + +if not python_nondynamic.is_python_builtin(): + try: + bb.cc = 3 + print("bb.cc = {}".format(bb.cc)) + print("B.cc = {}".format(B.cc)) + raise RuntimeError("B.cc class variable messes up nondynamic-ness of B") + except AttributeError as e: + debug_print(e) + pass + diff --git a/Examples/test-suite/python/python_overload_simple_cast_runme.py b/Examples/test-suite/python/python_overload_simple_cast_runme.py index 79ef6cd2e..d4cb8a37a 100644 --- a/Examples/test-suite/python/python_overload_simple_cast_runme.py +++ b/Examples/test-suite/python/python_overload_simple_cast_runme.py @@ -168,9 +168,9 @@ ullmaxd = 9007199254740992.0 ullmin = 0 ullmind = 0.0 if ull(ullmin) != ullmin: - raise runtimeerror, "ull(ullmin)" + raise RuntimeError, "ull(ullmin)" if ull(ullmax) != ullmax: - raise runtimeerror, "ull(ullmax)" + raise RuntimeError, "ull(ullmax)" if ull(ullmind) != ullmind: raise RuntimeError, "ull(ullmind)" if ull(ullmaxd) != ullmaxd: @@ -183,9 +183,9 @@ llmin = -9223372036854775808 llmaxd = 9007199254740992.0 llmind = -9007199254740992.0 if ll(llmin) != llmin: - raise runtimeerror, "ll(llmin)" + raise RuntimeError, "ll(llmin)" if ll(llmax) != llmax: - raise runtimeerror, "ll(llmax)" + raise RuntimeError, "ll(llmax)" if ll(llmind) != llmind: raise RuntimeError, "ll(llmind)" if ll(llmaxd) != llmaxd: diff --git a/Examples/test-suite/python/python_pickle_runme.py b/Examples/test-suite/python/python_pickle_runme.py new file mode 100644 index 000000000..27c67ae10 --- /dev/null +++ b/Examples/test-suite/python/python_pickle_runme.py @@ -0,0 +1,29 @@ +import python_pickle + +import pickle +import sys + +def check(p): + msg = p.msg + if msg != "hi there": + raise RuntimeError("Bad, got: " + msg) + +python_pickle.cvar.debug = False + +p = python_pickle.PickleMe("hi there") +check(p) + +r = p.__reduce__() +if python_pickle.cvar.debug: + print "__reduce__ returned:", r +pickle_string = pickle.dumps(p) +newp = pickle.loads(pickle_string) +check(newp) + +# Not yet working... some crash and others are not producing a sensible "can't be pickled" error +#nfp = python_pickle.NotForPickling("no no") +#print nfp.__reduce__() +#pickle_string = pickle.dumps(nfp) +#print pickle_string +#newp = pickle.loads(pickle_string) +#print newp.msg diff --git a/Examples/test-suite/python/python_pybuf_runme3.py b/Examples/test-suite/python/python_pybuf_runme3.py deleted file mode 100644 index 4e57b69e8..000000000 --- a/Examples/test-suite/python/python_pybuf_runme3.py +++ /dev/null @@ -1,41 +0,0 @@ -# run: -# python python_pybuf_runme3.py benchmark -# for the benchmark, other wise the test case will be run -import python_pybuf -import sys -if len(sys.argv) >= 2 and sys.argv[1] == "benchmark": - # run the benchmark - import time - k = 1000000 # number of times to excute the functions - - t = time.time() - a = bytearray(b'hello world') - for i in range(k): - pybuf.title1(a) - print("Time used by bytearray:", time.time() - t) - - t = time.time() - b = 'hello world' - for i in range(k): - pybuf.title2(b) - print("Time used by string:", time.time() - t) -else: - # run the test case - buf1 = bytearray(10) - buf2 = bytearray(50) - - pybuf.func1(buf1) - assert buf1 == b'a' * 10 - - pybuf.func2(buf2) - assert buf2.startswith(b"Hello world!\x00") - - count = pybuf.func3(buf2) - assert count == 10 # number of alpha and number in 'Hello world!' - - length = pybuf.func4(buf2) - assert length == 12 - - buf3 = bytearray(b"hello") - pybuf.title1(buf3) - assert buf3 == b'Hello' diff --git a/Examples/test-suite/python/python_pybuffer_runme.py b/Examples/test-suite/python/python_pybuffer_runme.py new file mode 100644 index 000000000..8ecdb523b --- /dev/null +++ b/Examples/test-suite/python/python_pybuffer_runme.py @@ -0,0 +1,46 @@ +# run: +# python python_pybuffer_runme.py benchmark +# for the benchmark, other wise the test case will be run +import python_pybuffer +import sys + +def check(flag): + if not flag: + raise RuntimeError("Test failed") + +if len(sys.argv) >= 2 and sys.argv[1] == "benchmark": + # run the benchmark + import time + k = 1000000 # number of times to execute the functions + + t = time.time() + a = bytearray(b"hello world") + for i in range(k): + python_pybuffer.title1(a) + print "Time used by bytearray:", time.time() - t + + t = time.time() + b = "hello world" + for i in range(k): + python_pybuffer.title2(b) + print "Time used by string:", time.time() - t +else: + # run the test case + buf1 = bytearray(10) + buf2 = bytearray(50) + + python_pybuffer.func1(buf1) + check(buf1 == b"a" * 10) + + python_pybuffer.func2(buf2) + check(buf2.startswith(b"Hello world!\x00")) + + count = python_pybuffer.func3(buf2) + check(count == 10) # number of alpha and number in 'Hello world!' + + length = python_pybuffer.func4(buf2) + check(length == 12) + + buf3 = bytearray(b"hello") + python_pybuffer.title1(buf3) + check(buf3 == b"Hello") diff --git a/Examples/test-suite/python/python_pythoncode_runme.py b/Examples/test-suite/python/python_pythoncode_runme.py index da238780d..c27f4452d 100644 --- a/Examples/test-suite/python/python_pythoncode_runme.py +++ b/Examples/test-suite/python/python_pythoncode_runme.py @@ -3,3 +3,7 @@ import python_pythoncode # No need to actually do anything, this is a regression test for a bug which # caused an invalid python_pythoncode.py to be generated, so if we can import # it the bug is still fixed. + +# A later test enhancement checking __new__ requires some code... +f = python_pythoncode.get_foo() +f = python_pythoncode.Foo() diff --git a/Examples/test-suite/python/python_richcompare_runme.py b/Examples/test-suite/python/python_richcompare_runme.py index a68da2f98..724d1d73c 100644 --- a/Examples/test-suite/python/python_richcompare_runme.py +++ b/Examples/test-suite/python/python_richcompare_runme.py @@ -1,4 +1,10 @@ import python_richcompare +import sys + +def check_unorderable_types(exception): +# if str(exception).find("unorderable types") == -1: +# raise RuntimeError("A TypeError 'unorderable types' exception was expected"), None, sys.exc_info()[2] + pass # Exception message seems to vary from one version of Python to another base1 = python_richcompare.BaseClass(1) base2 = python_richcompare.BaseClass(2) @@ -65,6 +71,18 @@ if (b1 == a1): raise RuntimeError( "Comparing equivalent instances of different subclasses, == returned True") +# Check comparison to other objects +#------------------------------------------------------------------------------- +if (base1 == 42) : + raise RuntimeError("Comparing class to incompatible type, == returned True") +if not (base1 != 42) : + raise RuntimeError("Comparing class to incompatible type, != returned False") + +if (a1 == 42) : + raise RuntimeError("Comparing class (with overloaded operator ==) to incompatible type, == returned True") +if not (a1 != 42) : + raise RuntimeError("Comparing class (with overloaded operator ==) to incompatible type, != returned False") + # Check inequalities #------------------------------------------------------------------------- @@ -80,6 +98,40 @@ if not (a2 >= b2): if not (a2 <= b2): raise RuntimeError("operator<= failed") +# Check inequalities to other objects +#------------------------------------------------------------------------------- +if sys.version_info[0:2] < (3, 0): + if (base1 < 42): + raise RuntimeError("Comparing class to incompatible type, < returned True") + if (base1 <= 42): + raise RuntimeError("Comparing class to incompatible type, <= returned True") + if not (base1 > 42): + raise RuntimeError("Comparing class to incompatible type, > returned False") + if not (base1 >= 42): + raise RuntimeError("Comparing class to incompatible type, >= returned False") +else: + # Python 3 throws: TypeError: unorderable types + try: + res = base1 < 42 + raise RuntimeError("Failed to throw") + except TypeError,e: + check_unorderable_types(e) + try: + res = base1 <= 42 + raise RuntimeError("Failed to throw") + except TypeError,e: + check_unorderable_types(e) + try: + res = base1 > 42 + raise RuntimeError("Failed to throw") + except TypeError,e: + check_unorderable_types(e) + try: + res = base1 >= 42 + raise RuntimeError("Failed to throw") + except TypeError,e: + check_unorderable_types(e) + # Check inequalities used for ordering #------------------------------------------------------------------------- diff --git a/Examples/test-suite/python/python_strict_unicode_runme.py b/Examples/test-suite/python/python_strict_unicode_runme.py index 642e127fa..e7fae2556 100644 --- a/Examples/test-suite/python/python_strict_unicode_runme.py +++ b/Examples/test-suite/python/python_strict_unicode_runme.py @@ -1,16 +1,8 @@ import python_strict_unicode -from sys import version_info -test_bytes = 'hello \x01world\x99' -BYTES = 'BYTES' -test_unicode = u'h\udce9llo w\u00f6rld' - -# Python < 2.6 rejects the b prefix for byte string literals as a SyntaxError, -# so instead create Python3 bytes objects by encoding unicode strings as -# latin-1, which maps code points 0-255 directly to the corresponding bytes. -if version_info[0] >= 3: - test_bytes = test_bytes.encode('latin-1') - BYTES = BYTES.encode('latin-1') +test_bytes = b"hello \x01world\x99" +BYTES = b"BYTES" +test_unicode = u"h\udce9llo w\u00f6rld" # Test that byte string inputs and outputs work as expected bdbl = python_strict_unicode.double_str(test_bytes) @@ -28,12 +20,12 @@ if type(bout) != type(BYTES): udbl = python_strict_unicode.double_wstr(test_unicode) if udbl != test_unicode + test_unicode: raise RuntimeError("Failed to double wide string") -if type(udbl) != type(u''): +if type(udbl) != type(u""): raise RuntimeError("Wrong type output for wide string") uout = python_strict_unicode.same_wstr(test_unicode) if uout != test_unicode: raise RuntimeError("Failed to copy wchar_t*") -if type(uout) != type(u''): +if type(uout) != type(u""): raise RuntimeError("Wrong type output for wchar_t*") # Test that overloading is handled properly @@ -43,9 +35,9 @@ if bovr != BYTES: if type(bovr) != type(BYTES): raise RuntimeError("Wrong type output from overload") uovr = python_strict_unicode.overload(test_unicode) -if uovr != u'UNICODE': +if uovr != u"UNICODE": raise RuntimeError("Failed to return unicode from overload") -if type(uovr) != type(u''): +if type(uovr) != type(u""): raise RuntimeERror("Wrong type output from overload") # Test that bytes aren't accepted as wide strings and unicode isn't accepted as narrow strings diff --git a/Examples/test-suite/python/reference_global_vars_runme.py b/Examples/test-suite/python/reference_global_vars_runme.py index 6c2d181ac..6f86527b7 100644 --- a/Examples/test-suite/python/reference_global_vars_runme.py +++ b/Examples/test-suite/python/reference_global_vars_runme.py @@ -13,8 +13,8 @@ cvar.var_bool = createref_bool(True) if value_bool(cvar.var_bool) != True: raise RuntimeError -cvar.var_char = createref_char('w') -if value_char(cvar.var_char) != 'w': +cvar.var_char = createref_char("w") +if value_char(cvar.var_char) != "w": raise RuntimeError cvar.var_unsigned_char = createref_unsigned_char(10) diff --git a/Examples/test-suite/python/return_const_value_runme.py b/Examples/test-suite/python/return_const_value_runme.py index 947102840..ff3bd5f02 100644 --- a/Examples/test-suite/python/return_const_value_runme.py +++ b/Examples/test-suite/python/return_const_value_runme.py @@ -3,10 +3,10 @@ import sys p = return_const_value.Foo_ptr_getPtr() if (p.getVal() != 17): - print "Runtime test1 faild. p.getVal()=", p.getVal() + print "Runtime test1 failed. p.getVal()=", p.getVal() sys.exit(1) p = return_const_value.Foo_ptr_getConstPtr() if (p.getVal() != 17): - print "Runtime test2 faild. p.getVal()=", p.getVal() + print "Runtime test2 failed. p.getVal()=", p.getVal() sys.exit(1) diff --git a/Examples/test-suite/python/smart_pointer_member_runme.py b/Examples/test-suite/python/smart_pointer_member_runme.py index ce91da2bd..d2ed87e79 100644 --- a/Examples/test-suite/python/smart_pointer_member_runme.py +++ b/Examples/test-suite/python/smart_pointer_member_runme.py @@ -1,9 +1,6 @@ from smart_pointer_member import * -def is_new_style_class(cls): - return hasattr(cls, "__class__") - f = Foo() f.y = 1 @@ -24,6 +21,5 @@ if b.x != f.x: if b.z != f.z: raise RuntimeError -if is_new_style_class(Bar): # feature not supported in old style classes - if Foo.z == Bar.z: - raise RuntimeError +if Foo.z == Bar.z: + raise RuntimeError diff --git a/Examples/test-suite/python/std_containers_runme.py b/Examples/test-suite/python/std_containers_runme.py index d4625daa0..7404cd5f4 100644 --- a/Examples/test-suite/python/std_containers_runme.py +++ b/Examples/test-suite/python/std_containers_runme.py @@ -60,15 +60,24 @@ if mi[0][1] != mc[0][1]: map = {} -map['hello'] = 1 -map['hi'] = 2 -map['3'] = 2 +map["hello"] = 1 +map["hi"] = 2 +map["3"] = 2 imap = std_containers.mapident(map) for k in map: if map[k] != imap[k]: raise RuntimeError, "bad map" +# Test __contains__ (required for 'x in y' to work) +if not imap.__contains__("hello"): + raise RuntimeError("hello imap.__contains__") +if "hello" not in imap: + raise RuntimeError("hello not in imap") +if imap.__contains__("oops"): + raise RuntimeError("oops imap.__contains__") +if "oops" in imap: + raise RuntimeError("oops in imap") mapc = {} c1 = std_containers.C() @@ -114,3 +123,14 @@ for i in s: if i != j: raise RuntimeError j = j + 1 + +# Test __contains__ (required for 'x in y' to work) +if not s.__contains__(3): + raise RuntimeError("3 s.__contains__") +if 3 not in s: + raise RuntimeError("3 not in s") +if s.__contains__(-1): + raise RuntimeError("-1 s.__contains__") +if -1 in s: + raise RuntimeError("-1 in s") + diff --git a/Examples/test-suite/python/swigobject_runme.py b/Examples/test-suite/python/swigobject_runme.py index 346b05d40..de232f580 100644 --- a/Examples/test-suite/python/swigobject_runme.py +++ b/Examples/test-suite/python/swigobject_runme.py @@ -15,11 +15,11 @@ lthis = long(a.this) # match pointer value, but deal with leading zeros on 8/16 bit systems and # different C++ compilers interpretation of %p xstr1 = "%016X" % (lthis,) -xstr1 = str.lstrip(xstr1, '0') +xstr1 = str.lstrip(xstr1, "0") xstr2 = pointer_str(a) xstr2 = str.replace(xstr2, "0x", "") xstr2 = str.replace(xstr2, "0X", "") -xstr2 = str.lstrip(xstr2, '0') +xstr2 = str.lstrip(xstr2, "0") xstr2 = str.upper(xstr2) if xstr1 != xstr2: diff --git a/Examples/test-suite/python/template_class_reuse_name_runme.py b/Examples/test-suite/python/template_class_reuse_name_runme.py new file mode 100644 index 000000000..3ce427508 --- /dev/null +++ b/Examples/test-suite/python/template_class_reuse_name_runme.py @@ -0,0 +1,42 @@ +from template_class_reuse_name import * + +Bool1().tt() +Bool1False().ff() + +Bool2().tt() +Bool2False().ff() + +Bool3().tt() +Bool3False().ff() + +Bool4().tt() +Bool4False().ff() + + +BoolForward1().tt() +BoolForward1False().ff() + +BoolForward2().tt() +BoolForward2False().ff() + +BoolForward3().tt() +BoolForward3False().ff() + +BoolForward4().tt() +BoolForward4False().ff() + + +IntBool1().tt() +IntBool1False().ff() + +IntBool2().tt() +IntBool2False().ff() + +IntBool3().tt() +IntBool3False().ff() + +IntBool4().tt() +IntBool4False().ff() + +Duplicate2_0().n() +Duplicate3().n() diff --git a/Examples/test-suite/python/template_default_cache_runme.py b/Examples/test-suite/python/template_default_cache_runme.py new file mode 100644 index 000000000..ffe155acf --- /dev/null +++ b/Examples/test-suite/python/template_default_cache_runme.py @@ -0,0 +1,9 @@ +import template_default_cache + +ap = template_default_cache.get_mp_a(); +bp = template_default_cache.get_mp_b(); + +if not isinstance(ap, template_default_cache.AModelPtr): + raise RuntimeError("get_mp_a fail") +if not isinstance(bp, template_default_cache.BModelPtr): + raise RuntimeError("get_mp_b fail") diff --git a/Examples/test-suite/python/template_typedef_cplx2_runme.py b/Examples/test-suite/python/template_typedef_cplx2_runme.py index 3043d4285..161bd51fc 100644 --- a/Examples/test-suite/python/template_typedef_cplx2_runme.py +++ b/Examples/test-suite/python/template_typedef_cplx2_runme.py @@ -11,8 +11,8 @@ except: print d, "is not an instance" raise RuntimeError -s = '%s' % d -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % d +if str.find(s, "ArithUnaryFunction") == -1: print d, "is not an ArithUnaryFunction" raise RuntimeError @@ -23,8 +23,8 @@ except: print e, "is not an instance" raise RuntimeError -s = '%s' % e -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % e +if str.find(s, "ArithUnaryFunction") == -1: print e, "is not an ArithUnaryFunction" raise RuntimeError @@ -40,8 +40,8 @@ except: print c, "is not an instance" raise RuntimeError -s = '%s' % c -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % c +if str.find(s, "ArithUnaryFunction") == -1: print c, "is not an ArithUnaryFunction" raise RuntimeError @@ -52,8 +52,8 @@ except: print f, "is not an instance" raise RuntimeError -s = '%s' % f -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % f +if str.find(s, "ArithUnaryFunction") == -1: print f, "is not an ArithUnaryFunction" raise RuntimeError @@ -68,8 +68,8 @@ except: print g, "is not an instance" raise RuntimeError -s = '%s' % g -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % g +if str.find(s, "ArithUnaryFunction") == -1: print g, "is not an ArithUnaryFunction" raise RuntimeError @@ -81,8 +81,8 @@ except: print h, "is not an instance" raise RuntimeError -s = '%s' % h -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % h +if str.find(s, "ArithUnaryFunction") == -1: print h, "is not an ArithUnaryFunction" raise RuntimeError diff --git a/Examples/test-suite/python/template_typedef_cplx_runme.py b/Examples/test-suite/python/template_typedef_cplx_runme.py index afb97d070..1846739eb 100644 --- a/Examples/test-suite/python/template_typedef_cplx_runme.py +++ b/Examples/test-suite/python/template_typedef_cplx_runme.py @@ -11,8 +11,8 @@ except: print d, "is not an instance" raise RuntimeError -s = '%s' % d -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % d +if str.find(s, "ArithUnaryFunction") == -1: print d, "is not an ArithUnaryFunction" raise RuntimeError @@ -23,8 +23,8 @@ except: print e, "is not an instance" raise RuntimeError -s = '%s' % e -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % e +if str.find(s, "ArithUnaryFunction") == -1: print e, "is not an ArithUnaryFunction" raise RuntimeError @@ -40,8 +40,8 @@ except: print c, "is not an instance" raise RuntimeError -s = '%s' % c -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % c +if str.find(s, "ArithUnaryFunction") == -1: print c, "is not an ArithUnaryFunction" raise RuntimeError @@ -52,8 +52,8 @@ except: print f, "is not an instance" raise RuntimeError -s = '%s' % f -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % f +if str.find(s, "ArithUnaryFunction") == -1: print f, "is not an ArithUnaryFunction" raise RuntimeError @@ -68,8 +68,8 @@ except: print g, "is not an instance" raise RuntimeError -s = '%s' % g -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % g +if str.find(s, "ArithUnaryFunction") == -1: print g, "is not an ArithUnaryFunction" raise RuntimeError @@ -81,7 +81,7 @@ except: print h, "is not an instance" raise RuntimeError -s = '%s' % h -if str.find(s, 'ArithUnaryFunction') == -1: +s = "%s" % h +if str.find(s, "ArithUnaryFunction") == -1: print h, "is not an ArithUnaryFunction" raise RuntimeError diff --git a/Examples/test-suite/python/template_using_directive_typedef_runme.py b/Examples/test-suite/python/template_using_directive_typedef_runme.py new file mode 100644 index 000000000..363a3b754 --- /dev/null +++ b/Examples/test-suite/python/template_using_directive_typedef_runme.py @@ -0,0 +1,15 @@ +import template_using_directive_typedef + +vo = template_using_directive_typedef.Vector_Obj(); + +h = template_using_directive_typedef.Holder(); +h.holder_use1(vo, vo, vo); +h.holder_use2(vo, vo, vo); +h.holder_use3(vo, vo, vo); + +template_using_directive_typedef.tns_holder_use(vo, vo); +template_using_directive_typedef.tns_use(vo, vo, vo); +template_using_directive_typedef.global_holder_use(vo); +template_using_directive_typedef.global_use(vo, vo, vo); +template_using_directive_typedef.ns1_holder_use(vo); +template_using_directive_typedef.ns2_holder_use(vo, vo, vo, vo); diff --git a/Examples/test-suite/python/typedef_classforward_same_name_runme.py b/Examples/test-suite/python/typedef_classforward_same_name_runme.py new file mode 100644 index 000000000..61f45fbee --- /dev/null +++ b/Examples/test-suite/python/typedef_classforward_same_name_runme.py @@ -0,0 +1,11 @@ +from typedef_classforward_same_name import * + +foo = Foo() +foo.x = 5 +if extractFoo(foo) != 5: + raise RuntimeError("unexpected value") + +boo = Boo() +boo.x = 5 +if extractBoo(boo) != 5: + raise RuntimeError("unexpected value") diff --git a/Examples/test-suite/python/typedef_funcptr_runme.py b/Examples/test-suite/python/typedef_funcptr_runme.py new file mode 100644 index 000000000..a186963f7 --- /dev/null +++ b/Examples/test-suite/python/typedef_funcptr_runme.py @@ -0,0 +1,20 @@ +import typedef_funcptr + +a = 100 +b = 10 + +if typedef_funcptr.do_op(a,b,typedef_funcptr.addf) != 110: + raise RuntimeError("addf failed") +if typedef_funcptr.do_op(a,b,typedef_funcptr.subf) != 90: + raise RuntimeError("subf failed") + +if typedef_funcptr.do_op_typedef_int(a,b,typedef_funcptr.addf) != 110: + raise RuntimeError("addf failed") +if typedef_funcptr.do_op_typedef_int(a,b,typedef_funcptr.subf) != 90: + raise RuntimeError("subf failed") + +if typedef_funcptr.do_op_typedef_Integer(a,b,typedef_funcptr.addf) != 110: + raise RuntimeError("addf failed") +if typedef_funcptr.do_op_typedef_Integer(a,b,typedef_funcptr.subf) != 90: + raise RuntimeError("subf failed") + diff --git a/Examples/test-suite/python/typemap_documentation_runme.py b/Examples/test-suite/python/typemap_documentation_runme.py new file mode 100644 index 000000000..3d1c6fa8c --- /dev/null +++ b/Examples/test-suite/python/typemap_documentation_runme.py @@ -0,0 +1,20 @@ +import typemap_documentation + +f = typemap_documentation.Foo() +f.x = 55 +b = typemap_documentation.Bar() +b.y = 44 + +if 55 != typemap_documentation.GrabVal(f): + raise RuntimeError("bad value") + +try: + typemap_documentation.GrabVal(b) + raise RuntimeError("unexpected exception") +except TypeError: + pass + +if 55 != typemap_documentation.GrabValFooBar(f): + raise RuntimeError("bad f value") +if 44 != typemap_documentation.GrabValFooBar(b): + raise RuntimeError("bad b value") diff --git a/Examples/test-suite/python/typemap_template_typedef_runme.py b/Examples/test-suite/python/typemap_template_typedef_runme.py new file mode 100644 index 000000000..a2458367e --- /dev/null +++ b/Examples/test-suite/python/typemap_template_typedef_runme.py @@ -0,0 +1,32 @@ +from typemap_template_typedef import * + +def check(got, expected): + if got != expected: + raise RuntimeError("got: " + str(got) + " expected: " + str(expected)) + +x = XXXInt() + +check(x.aa1(0), 0) +check(x.aa2(0), 55) +check(x.aa3(0), 0) +check(aa1(0), 0) +check(aa2(0), 0) + +check(x.bb1(0), 0) +check(x.bb2(0), 66) +check(x.bb3(0), 0) +check(bb1(0), 0) +check(bb2(0), 0) + +check(x.cc1(0), 0) +check(x.cc2(0), 77) +check(x.cc3(0), 77) +check(cc1(0), 0) +check(cc2(0), 0) + +check(x.dd1(0), 0) +check(x.dd2(0), 88) +check(x.dd3(0), 0) +check(dd1(0), 0) +check(dd2(0), 0) + diff --git a/Examples/test-suite/python/unicode_strings_runme.py b/Examples/test-suite/python/unicode_strings_runme.py index fa9c51437..4e661f00e 100644 --- a/Examples/test-suite/python/unicode_strings_runme.py +++ b/Examples/test-suite/python/unicode_strings_runme.py @@ -5,13 +5,13 @@ import unicode_strings # The 'u' string prefix isn't valid in Python 3.0 - 3.2 and is redundant # in 3.3+. Since this file is run through 2to3 before testing, though, # mark this as a unicode string in 2.x so it'll become a str in 3.x. -test_string = u'h\udce9llo w\u00f6rld' +test_string = u"h\udce9llo w\u00f6rld" if sys.version_info[0:2] >= (3, 1): if unicode_strings.non_utf8_c_str() != test_string: - raise ValueError('Test comparison mismatch') + raise ValueError("Test comparison mismatch") if unicode_strings.non_utf8_std_string() != test_string: - raise ValueError('Test comparison mismatch') + raise ValueError("Test comparison mismatch") def check(s1, s2): if s1 != s2: @@ -25,3 +25,13 @@ if sys.version_info[0:2] < (3, 0): check(unicode_strings.charstring(unicode("hello4")), "hello4") unicode_strings.charstring(u"hell\xb05") unicode_strings.charstring(u"hell\u00f66") + +low_surrogate_string = u"\udcff" +try: + unicode_strings.instring(low_surrogate_string) + # Will succeed with Python 2 +except TypeError, e: + # Python 3 will fail the PyUnicode_AsUTF8String conversion resulting in a TypeError. + # The real error is actually: + # UnicodeEncodeError: 'utf-8' codec can't encode character '\udcff' in position 0: surrogates not allowed + pass diff --git a/Examples/test-suite/python/varargs_overload_runme.py b/Examples/test-suite/python/varargs_overload_runme.py index 37958620c..6f5a70222 100644 --- a/Examples/test-suite/python/varargs_overload_runme.py +++ b/Examples/test-suite/python/varargs_overload_runme.py @@ -28,3 +28,35 @@ if varargs_overload.vararg_over4(123) != "123": if varargs_overload.vararg_over4("Hello", 123) != "Hello": raise RuntimeError, "Failed" + + +# Same as above but non-vararg function declared first + +if varargs_overload.vararg_over6("Hello") != "Hello": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over6(2) != "2": + raise RuntimeError, "Failed" + + +if varargs_overload.vararg_over7("Hello") != "Hello": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over7(2, 2.2) != "2 2.2": + raise RuntimeError, "Failed" + + +if varargs_overload.vararg_over8("Hello") != "Hello": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over8(2, 2.2, "hey") != "2 2.2 hey": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over9("Hello") != "Hello": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over9(123) != "123": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over9("Hello", 123) != "Hello": + raise RuntimeError, "Failed" diff --git a/Examples/test-suite/python/varargs_runme.py b/Examples/test-suite/python/varargs_runme.py index 7105ba8d7..277ea757a 100644 --- a/Examples/test-suite/python/varargs_runme.py +++ b/Examples/test-suite/python/varargs_runme.py @@ -30,7 +30,5 @@ if varargs.test_plenty("Hello", 1, 2) != "Hello": try: varargs.test_plenty("Hello", 1, 2, 3) raise RuntimeError -except NotImplementedError: - pass except TypeError: pass diff --git a/Examples/test-suite/python_append.i b/Examples/test-suite/python_append.i index 2a71b5784..049494319 100644 --- a/Examples/test-suite/python_append.i +++ b/Examples/test-suite/python_append.i @@ -17,11 +17,11 @@ def clearstaticpath(): staticfuncpath = None %} -%pythonappend Test::func %{ +%pythonappend Test::funk %{ funcpath = os.path.dirname(funcpath) %} -%pythonprepend Test::func %{ +%pythonprepend Test::funk %{ global funcpath funcpath = mypath %} @@ -46,7 +46,7 @@ import os.path class Test { public: static void static_func() {}; - void func() {}; + void funk() {}; }; #ifdef SWIGPYTHON_BUILTIN diff --git a/Examples/test-suite/python_builtin.i b/Examples/test-suite/python_builtin.i index e2c453d54..994c625e8 100644 --- a/Examples/test-suite/python_builtin.i +++ b/Examples/test-suite/python_builtin.i @@ -2,6 +2,14 @@ %module python_builtin +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) +#define TESTCASE_THROW2(T1, T2) throw(T1, T2) +%{ +#define TESTCASE_THROW1(T1) +#define TESTCASE_THROW2(T1, T2) +%} + %inline %{ #ifdef SWIGPYTHON_BUILTIN bool is_python_builtin() { return true; } @@ -21,7 +29,7 @@ struct ValueStruct { }; %} -// Test 1 for tp_hash +// Test 1a for tp_hash #if defined(SWIGPYTHON_BUILTIN) %feature("python:tp_hash") SimpleValue "SimpleValueHashFunction" #endif @@ -49,6 +57,24 @@ hashfunc test_hashfunc_cast() { } %} +// Test 1b for tp_hash +#if defined(SWIGPYTHON_BUILTIN) +%feature("python:slot", "tp_hash", functype="hashfunc") SimpleValue2::HashFunc; +#endif + +%inline %{ +struct SimpleValue2 { + int value; + SimpleValue2(int value) : value(value) {} +#if PY_VERSION_HEX >= 0x03020000 + typedef Py_hash_t HashType; +#else + typedef long HashType; +#endif + HashType HashFunc() { return (HashType)value; } +}; +%} + // Test 2 for tp_hash #if defined(SWIGPYTHON_BUILTIN) %feature("python:slot", "tp_hash", functype="hashfunc") BadHashFunctionReturnType::bad_hash_function; @@ -136,3 +162,86 @@ void Dealloc2Destroyer(PyObject *v) { }; int MyClass::less_than_counts = 0; %} + +// Test 6 add in container __getitem__ to support basic sequence protocol +// Tests overloaded functions being used for more than one slot (mp_subscript and sq_item) +%include +%include +%apply int {Py_ssize_t} +%typemap(in) PySliceObject * { + if (!PySlice_Check($input)) + SWIG_exception(SWIG_TypeError, "in method '$symname', argument $argnum of type '$type'"); + $1 = (PySliceObject *)$input; +} +%typemap(typecheck,precedence=300) PySliceObject* { + $1 = PySlice_Check($input); +} + +%feature("python:slot", "mp_subscript", functype="binaryfunc") SimpleArray::__getitem__(PySliceObject *slice); +%feature("python:slot", "sq_item", functype="ssizeargfunc") SimpleArray::__getitem__(Py_ssize_t n); +%feature("python:slot", "sq_length", functype="lenfunc") SimpleArray::__len__; +%inline %{ + class SimpleArray { + Py_ssize_t size; + int numbers[5]; + public: + SimpleArray(Py_ssize_t size) : size(size) { + for (Py_ssize_t x = 0; x= (int)size) + throw std::out_of_range("Index too large"); + return numbers[n]; + } + + SimpleArray __getitem__(PySliceObject *slice) TESTCASE_THROW2(std::out_of_range, std::invalid_argument) { + if (!PySlice_Check(slice)) + throw std::invalid_argument("Slice object expected"); + Py_ssize_t i, j, step; +#if PY_VERSION_HEX >= 0x03020000 + PySlice_GetIndices((PyObject *)slice, size, &i, &j, &step); +#else + PySlice_GetIndices((PySliceObject *)slice, size, &i, &j, &step); +#endif + if (step != 1) + throw std::invalid_argument("Only a step size of 1 is implemented"); + + { + Py_ssize_t ii = i<0 ? 0 : i>=size ? size-1 : i; + Py_ssize_t jj = j<0 ? 0 : j>=size ? size-1 : j; + if (ii > jj) + throw std::invalid_argument("getitem i should not be larger than j"); + SimpleArray n(jj-ii); + for (Py_ssize_t x = 0; xnum : val; + return ANumber(val); + } + int Value() const { + return num; + } +}; +%} + diff --git a/Examples/test-suite/python_extranative.i b/Examples/test-suite/python_extranative.i new file mode 100644 index 000000000..04361b3e6 --- /dev/null +++ b/Examples/test-suite/python_extranative.i @@ -0,0 +1,16 @@ +%module(extranative="1") python_extranative + +%include +%include + +%template(VectorString) std::vector; + +%inline %{ +std::vector make_vector_string() { + std::vector vs; + vs.push_back("one"); + vs.push_back("two"); + return vs; +} +%} + diff --git a/Examples/test-suite/python_moduleimport.i b/Examples/test-suite/python_moduleimport.i new file mode 100644 index 000000000..f62547dcd --- /dev/null +++ b/Examples/test-suite/python_moduleimport.i @@ -0,0 +1,26 @@ +#if !defined(SWIGPYTHON_BUILTIN) +%define MODULEIMPORT +" +# print 'Loading low-level module $module' +import $module +# print 'Module has loaded' +extra_import_variable = 'custom import of $module' +" +%enddef + +#else +%define MODULEIMPORT +" +# print 'Loading low-level module $module' +extra_import_variable = 'custom import of $module' +from $module import * +# print 'Module has loaded' +" +%enddef +#endif + +%module(moduleimport=MODULEIMPORT) python_moduleimport + +%inline %{ +int simple_function(int i) { return i; } +%} diff --git a/Examples/test-suite/python_nondynamic.i b/Examples/test-suite/python_nondynamic.i index 54a3f28ca..b08cec9e6 100644 --- a/Examples/test-suite/python_nondynamic.i +++ b/Examples/test-suite/python_nondynamic.i @@ -29,8 +29,6 @@ http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252158 - and works for modern (-modern) and plain python. - */ @@ -54,5 +52,14 @@ int b; }; + int retrieve_A_a(const struct A* self) { return self->a; } + int retrieve_A_b(const struct A* self) { return self->b; } +%} +%inline %{ +#ifdef SWIGPYTHON_BUILTIN +int is_python_builtin() { return 1; } +#else +int is_python_builtin() { return 0; } +#endif %} diff --git a/Examples/test-suite/python_pickle.i b/Examples/test-suite/python_pickle.i new file mode 100644 index 000000000..fbb3d05a8 --- /dev/null +++ b/Examples/test-suite/python_pickle.i @@ -0,0 +1,56 @@ +%module python_pickle + + +%include + +%extend PickleMe { +#if 0 +// Note: %pythoncode can't be used with -builtin +%pythoncode %{ +def __reduce__(self): + print "In Python __reduce__" + return (type(self), (self.msg, )) +%} +#else + // Equivalent to Python code above + PyObject *__reduce__() { + if (debug) + std::cout << "In C++ __reduce__" << std::endl; + PyObject *args = PyTuple_New(1); + PyTuple_SetItem(args, 0, SWIG_From_std_string(self->msg)); + + swig_type_info *ty = SWIGTYPE_p_PickleMe; + SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; +#if defined(SWIGPYTHON_BUILTIN) + PyObject *callable = (PyObject *)data->pytype; +#else + PyObject *callable = data->klass; +#endif + Py_INCREF(callable); + + PyObject *ret = PyTuple_New(2); + PyTuple_SetItem(ret, 0, callable); + PyTuple_SetItem(ret, 1, args); + return ret; + } +#endif +} + +%inline %{ +#include + +bool debug = false; + +struct PickleMe { + std::string msg; + PickleMe(const std::string& msg) : msg(msg) { + if (debug) + std::cout << "In C++ constructor " << " [" << msg << "]" << std::endl; + } +}; + +struct NotForPickling { + std::string msg; + NotForPickling(const std::string& msg) : msg(msg) {} +}; +%} diff --git a/Examples/test-suite/python_pybuf.i b/Examples/test-suite/python_pybuffer.i similarity index 91% rename from Examples/test-suite/python_pybuf.i rename to Examples/test-suite/python_pybuffer.i index 8e1302582..bff72bfa2 100644 --- a/Examples/test-suite/python_pybuf.i +++ b/Examples/test-suite/python_pybuffer.i @@ -1,6 +1,6 @@ -%module python_pybuf -%include -%include +%module python_pybuffer +%include +%include /*functions for the test case*/ %pybuffer_mutable_binary(char *buf1, int len); %pybuffer_mutable_string(char *buf2); @@ -28,7 +28,7 @@ ++count; return count; } - int func4(const char *buf4) + size_t func4(const char *buf4) { return strlen(buf4); } diff --git a/Examples/test-suite/python_pythoncode.i b/Examples/test-suite/python_pythoncode.i index 70474d44c..017f076c4 100644 --- a/Examples/test-suite/python_pythoncode.i +++ b/Examples/test-suite/python_pythoncode.i @@ -29,3 +29,33 @@ struct TYPE2 { struct TYPE { }; struct TYPE2 { }; %} + + +// Overriding __new__ test: https://github.com/swig/swig/pull/1357 +%inline %{ +class Foo { + public: + virtual ~Foo() {} + Foo() {} +}; + +Foo* get_foo() {return new Foo();} +%} + +%pythoncode %{ + print_debug = False +%} + +%extend Foo { + // Note that %pythoncode is not available with -builtin + %pythoncode %{ + def __new__(cls, *args, **kwargs): + if print_debug: + print('in Foo.__new__()') + return super(Foo, cls).__new__(cls) + + def __init__(self): + if print_debug: + print('in Foo.__init__()') + %} +}; diff --git a/Examples/test-suite/python_varargs_typemap.i b/Examples/test-suite/python_varargs_typemap.i index c7d8b83ec..d809bf1fa 100644 --- a/Examples/test-suite/python_varargs_typemap.i +++ b/Examples/test-suite/python_varargs_typemap.i @@ -11,7 +11,7 @@ argc = PyTuple_Size(varargs); if (argc > 10) { PyErr_SetString(PyExc_ValueError, "Too many arguments"); - return NULL; + SWIG_fail; } for (i = 0; i < argc; i++) { PyObject *pyobj = PyTuple_GetItem(varargs, i); @@ -20,15 +20,18 @@ PyObject *pystr; if (!PyUnicode_Check(pyobj)) { PyErr_SetString(PyExc_ValueError, "Expected a string"); - return NULL; + SWIG_fail; } pystr = PyUnicode_AsUTF8String(pyobj); + if (!pystr) { + SWIG_fail; + } str = strdup(PyBytes_AsString(pystr)); - Py_XDECREF(pystr); + Py_DECREF(pystr); %#else if (!PyString_Check(pyobj)) { PyErr_SetString(PyExc_ValueError, "Expected a string"); - return NULL; + SWIG_fail; } str = PyString_AsString(pyobj); %#endif diff --git a/Examples/test-suite/r/Makefile.in b/Examples/test-suite/r/Makefile.in index bc12ba671..33e9d90da 100644 --- a/Examples/test-suite/r/Makefile.in +++ b/Examples/test-suite/r/Makefile.in @@ -19,7 +19,18 @@ C_TEST_CASES += \ CPP_TEST_CASES += \ r_double_delete \ r_overload_array \ - r_sexp + r_sexp \ + r_overload_comma \ + r_use_isnull + +# These tests are failing because enums currently cannot handle +# arithmetic expressions + +FAILING_CPP_TESTS = \ + preproc_constants + +FAILING_C_TESTS = \ + preproc_constants_c include $(srcdir)/../common.mk @@ -52,7 +63,7 @@ include $(srcdir)/../common.mk # check for syntactic correctness run_testcase = \ if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" $(RUNTOOL) $(RUNR) $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) || (cat $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX)out ; false); \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" $(RUNTOOL) $(RUNR) $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) || (cat ./$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX)out ; false); \ else \ $(RUNTOOL) $(RUNR) ./$(SCRIPTPREFIX)$*$(WRAPSUFFIX) || (cat ./$(SCRIPTPREFIX)$*$(WRAPSUFFIX)out ; false); \ fi @@ -60,7 +71,7 @@ run_testcase = \ run_multitestcase = \ for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX) ]; then \ - env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" $(RUNTOOL) $(RUNR) $(SCRIPTDIR)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX) || (cat $(SCRIPTDIR)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX)out ; false); \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" $(RUNTOOL) $(RUNR) $(SCRIPTDIR)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX) || (cat ./$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX)out ; false); \ else \ $(RUNTOOL) $(RUNR) ./$(SCRIPTPREFIX)$${f}$(WRAPSUFFIX) || (cat ./$(SCRIPTPREFIX)$${f}$(WRAPSUFFIX)out ; false); \ fi; \ diff --git a/Examples/test-suite/r/enum_thorough_runme.R b/Examples/test-suite/r/enum_thorough_runme.R new file mode 100644 index 000000000..a0f1270b7 --- /dev/null +++ b/Examples/test-suite/r/enum_thorough_runme.R @@ -0,0 +1,452 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + +dyn.load(paste("enum_thorough", .Platform$dynlib.ext, sep="")) +source("enum_thorough.R") +cacheMetaData(1) + +## Anonymous enums are not wrapped by the R module +## + +# Colours - string interface, various function signatures +unittest('red', colourTest1('red')) +unittest('blue', colourTest1('blue')) +unittest('green', colourTest1('green')) + + +unittest('red', colourTest2('red')) +unittest('blue', colourTest2('blue')) +unittest('green', colourTest2('green')) + +unittest('red', colourTest3('red')) +unittest('blue', colourTest3('blue')) +unittest('green', colourTest3('green')) + +unittest('red', colourTest4('red')) +unittest('blue', colourTest4('blue')) +unittest('green', colourTest4('green')) + +## Colours - underlying integers +unittest(-1, enumToInteger('red', '_colour')) +unittest(0, enumToInteger('blue', '_colour')) +unittest(10, enumToInteger('green', '_colour')) + +######## +## enum variable, wrapped as a function +## Is initialization to 0 a "standard" +myColour() + +## Test setting and retrieving +myColour('green') +unittest('green', myColour()) + +######## +## SpeedClass + +s <- SpeedClass() +v <- "medium" +unittest(v, s$speedTest1(v)) +unittest(v, s$speedTest2(v)) +unittest(v, s$speedTest3(v)) +unittest(v, s$speedTest4(v)) +unittest(v, s$speedTest5(v)) +unittest(v, s$speedTest6(v)) +unittest(v, s$speedTest7(v)) +unittest(v, s$speedTest8(v)) + +## speedTest methods not in the class + +unittest(v, speedTest1(v)) +unittest(v, speedTest2(v)) +unittest(v, speedTest3(v)) +unittest(v, speedTest4(v)) +# enum reference +unittest(v, speedTest5(v)) + +## member access +s <- SpeedClass() +unittest("slow", s$mySpeedtd1) +# check integer value +unittest(10, enumToInteger(s$mySpeedtd1, "_SpeedClass__speed")) +# set and check +s$mySpeedtd1 <- "lightning" +unittest("lightning", s$mySpeedtd1) +unittest(31, enumToInteger(s$mySpeedtd1, "_SpeedClass__speed")) + +## Named anon - not wrapped nicely, but can be retrieved: + + +unittest("NamedAnon2", namedanon_NamedAnon2_get()) +unittest(0, enumToInteger(namedanon_NamedAnon1_get(), "_namedanon")) +unittest(1, enumToInteger(namedanon_NamedAnon2_get(), "_namedanon")) + +## Twonames +v <- "TwoNames1" +unittest(v, twonamesTest1(v)) +unittest(v, twonamesTest2(v)) +unittest(v, twonamesTest3(v)) +unittest(33, enumToInteger("TwoNames3", "_twonamestag")) + +tt <- TwoNamesStruct() +v <- "TwoNamesStruct1" +unittest(v, tt$twonamesTest1(v)) +unittest(v, tt$twonamesTest2(v)) +unittest(v, tt$twonamesTest3(v)) +## Try the wrong name +unittest(TRUE, is.na(tt$twonamesTest3("TwoNames1"))) + +## Namedanonspace +## can get the values + +v <- namedanonspace_NamedAnonSpace2_get() +unittest(v, namedanonspaceTest1(v)) +unittest(v, namedanonspaceTest2(v)) +unittest(v, namedanonspaceTest3(v)) +unittest(v, namedanonspaceTest4(v)) + +## scientists + +tt <- TemplateClassInt() + +g <- "galileo" +unittest(g, tt$scientistsTest1(g)) +unittest(g, tt$scientistsTest2(g)) +unittest(g, tt$scientistsTest3(g)) +unittest(g, tt$scientistsTest4(g)) +unittest(g, tt$scientistsTest5(g)) +unittest(g, tt$scientistsTest6(g)) +unittest(g, tt$scientistsTest7(g)) +unittest(g, tt$scientistsTest8(g)) +unittest(g, tt$scientistsTest9(g)) + +## This one is commented out in csharp too +## unittest(g, tt$scientistsTestA(g)) +unittest(g, tt$scientistsTestB(g)) +## This one is commented out in csharp too +## unittest(g, tt$scientistsTestC(g)) +unittest(g, tt$scientistsTestD(g)) +unittest(g, tt$scientistsTestE(g)) +unittest(g, tt$scientistsTestF(g)) +unittest(g, tt$scientistsTestG(g)) +unittest(g, tt$scientistsTestH(g)) +unittest(g, tt$scientistsTestI(g)) +# enum reference +unittest(g, tt$scientistsTestJ(g)) + + +unittest(g, scientistsTest1(g)) +unittest(g, scientistsTest2(g)) +unittest(g, scientistsTest3(g)) +unittest(g, scientistsTest4(g)) +unittest(g, scientistsTest5(g)) +unittest(g, scientistsTest6(g)) +unittest(g, scientistsTest7(g)) +## enum reference +unittest(g, scientistsTest8(g)) + +tt <- TClassInt() +b <- "bell" +unittest(b, tt$scientistsNameTest1(b)) +unittest(b, tt$scientistsNameTest2(b)) +unittest(b, tt$scientistsNameTest3(b)) +unittest(b, tt$scientistsNameTest4(b)) +unittest(b, tt$scientistsNameTest5(b)) +unittest(b, tt$scientistsNameTest6(b)) +unittest(b, tt$scientistsNameTest7(b)) +unittest(b, tt$scientistsNameTest8(b)) +unittest(b, tt$scientistsNameTest9(b)) + +## This one is commented out in csharp too +## unittest(b, tt$scientistsNameTestA(b)) +unittest(b, tt$scientistsNameTestB(b)) +## This one is commented out in csharp too +## unittest(b, tt$scientistsNameTestC(b)) +unittest(b, tt$scientistsNameTestD(b)) +unittest(b, tt$scientistsNameTestE(b)) +unittest(b, tt$scientistsNameTestF(b)) +unittest(b, tt$scientistsNameTestG(b)) +unittest(b, tt$scientistsNameTestH(b)) +unittest(b, tt$scientistsNameTestI(b)) + + +unittest(b, tt$scientistsNameSpaceTest1(b)) +unittest(b, tt$scientistsNameSpaceTest2(b)) +unittest(b, tt$scientistsNameSpaceTest3(b)) +unittest(b, tt$scientistsNameSpaceTest4(b)) +unittest(b, tt$scientistsNameSpaceTest5(b)) +unittest(b, tt$scientistsNameSpaceTest6(b)) +unittest(b, tt$scientistsNameSpaceTest7(b)) + +unittest(g, tt$scientistsOtherTest1(g)) +unittest(g, tt$scientistsOtherTest2(g)) +unittest(g, tt$scientistsOtherTest3(g)) +unittest(g, tt$scientistsOtherTest4(g)) +unittest(g, tt$scientistsOtherTest5(g)) +unittest(g, tt$scientistsOtherTest6(g)) +unittest(g, tt$scientistsOtherTest7(g)) + +## Global +unittest(b, scientistsNameTest1(b)) +unittest(b, scientistsNameTest2(b)) +unittest(b, scientistsNameTest3(b)) +unittest(b, scientistsNameTest4(b)) +unittest(b, scientistsNameTest5(b)) +unittest(b, scientistsNameTest6(b)) +unittest(b, scientistsNameTest7(b)) + +unittest(b, scientistsNameSpaceTest1(b)) +unittest(b, scientistsNameSpaceTest2(b)) +unittest(b, scientistsNameSpaceTest3(b)) +unittest(b, scientistsNameSpaceTest4(b)) +unittest(b, scientistsNameSpaceTest5(b)) +unittest(b, scientistsNameSpaceTest6(b)) +unittest(b, scientistsNameSpaceTest7(b)) + +unittest(b, scientistsNameSpaceTest8(b)) +unittest(b, scientistsNameSpaceTest9(b)) +unittest(b, scientistsNameSpaceTestA(b)) +unittest(b, scientistsNameSpaceTestB(b)) +unittest(b, scientistsNameSpaceTestC(b)) +unittest(b, scientistsNameSpaceTestD(b)) +unittest(b, scientistsNameSpaceTestE(b)) +unittest(b, scientistsNameSpaceTestF(b)) +unittest(b, scientistsNameSpaceTestG(b)) +unittest(b, scientistsNameSpaceTestH(b)) +unittest(b, scientistsNameSpaceTestI(b)) +unittest(b, scientistsNameSpaceTestJ(b)) +unittest(b, scientistsNameSpaceTestK(b)) +unittest(b, scientistsNameSpaceTestL(b)) + +## rename test +v <- "eek" +unittest(v, renameTest1(v)) +unittest(v, renameTest2(v)) + +## NewName +N <- NewNameStruct() +## Only half works: +unittest("kerboom", NewNameStruct_bang_get()) +## Can't put in "bang" in the call +## confirm with: +## get(".__E___OldNameStruct__enumeration") + +## TreeClass + +T <- TreesClass() +p <- "pine" + +unittest(p, T$treesTest1(p)) +unittest(p, T$treesTest2(p)) +unittest(p, T$treesTest3(p)) +unittest(p, T$treesTest4(p)) +unittest(p, T$treesTest5(p)) +unittest(p, T$treesTest6(p)) +unittest(p, T$treesTest7(p)) +unittest(p, T$treesTest8(p)) +unittest(p, T$treesTest9(p)) +unittest(p, T$treesTestA(p)) +unittest(p, T$treesTestB(p)) +unittest(p, T$treesTestC(p)) +unittest(p, T$treesTestD(p)) +unittest(p, T$treesTestE(p)) +unittest(p, T$treesTestF(p)) +unittest(p, T$treesTestG(p)) +unittest(p, T$treesTestH(p)) +unittest(p, T$treesTestI(p)) +unittest(p, T$treesTestJ(p)) +unittest(p, T$treesTestK(p)) +unittest(p, T$treesTestL(p)) +unittest(p, T$treesTestM(p)) +unittest(p, T$treesTestN(p)) +unittest(p, T$treesTestO(p)) + +unittest(p, treesTest1(p)) +unittest(p, treesTest2(p)) +unittest(p, treesTest3(p)) +unittest(p, treesTest4(p)) +unittest(p, treesTest5(p)) +unittest(p, treesTest6(p)) +unittest(p, treesTest7(p)) +unittest(p, treesTest8(p)) +unittest(p, treesTest9(p)) +unittest(p, treesTestA(p)) +unittest(p, treesTestB(p)) +unittest(p, treesTestC(p)) +unittest(p, treesTestD(p)) +unittest(p, treesTestE(p)) +unittest(p, treesTestF(p)) +unittest(p, treesTestG(p)) +unittest(p, treesTestH(p)) +unittest(p, treesTestI(p)) +unittest(p, treesTestJ(p)) +unittest(p, treesTestK(p)) +unittest(p, treesTestL(p)) +unittest(p, treesTestM(p)) +unittest(p, treesTestO(p)) +unittest(p, treesTestP(p)) +unittest(p, treesTestQ(p)) +unittest(p, treesTestR(p)) + +## Hair +h <- HairStruct() +g <- "ginger" +unittest(g, h$hairTest1(g)) +unittest(g, h$hairTest2(g)) +unittest(g, h$hairTest3(g)) +unittest(g, h$hairTest4(g)) +unittest(g, h$hairTest5(g)) +unittest(g, h$hairTest6(g)) +unittest(g, h$hairTest7(g)) +unittest(g, h$hairTest8(g)) +unittest(g, h$hairTest9(g)) +unittest(g, h$hairTestA(g)) +unittest(g, h$hairTestB(g)) + +r <- "red" +unittest(r, h$colourTest1(r)) +unittest(r, h$colourTest2(r)) + +nmA <- "NamedAnon1" +unittest(nmA, h$namedanonTest1(nmA)) +unittest("NamedAnonSpace2", h$namedanonspaceTest1("NamedAnonSpace2")) + +f <- "fir" + +unittest(f, h$treesGlobalTest1(f)) +unittest(f, h$treesGlobalTest2(f)) +unittest(f, h$treesGlobalTest3(f)) +unittest(f, h$treesGlobalTest4(f)) + +b <- "blonde" +unittest(b, hairTest1(b)) +unittest(b, hairTest2(b)) +unittest(b, hairTest3(b)) +unittest(b, hairTest4(b)) +unittest(b, hairTest5(b)) +unittest(b, hairTest6(b)) +unittest(b, hairTest7(b)) +unittest(b, hairTest8(b)) +unittest(b, hairTest9(b)) +unittest(b, hairTestA(b)) +unittest(b, hairTestB(b)) +## enum reference +unittest(b, hairTestC(b)) +unittest(b, hairTestA1(b)) +unittest(b, hairTestA2(b)) +unittest(b, hairTestA3(b)) +unittest(b, hairTestA4(b)) +unittest(b, hairTestA5(b)) +unittest(b, hairTestA6(b)) +unittest(b, hairTestA7(b)) +unittest(b, hairTestA8(b)) +unittest(b, hairTestA9(b)) +unittest(b, hairTestAA(b)) +unittest(b, hairTestAB(b)) +## enum reference +unittest(b, hairTestAC(b)) + +unittest(b, hairTestB1(b)) +unittest(b, hairTestB2(b)) +unittest(b, hairTestB3(b)) +unittest(b, hairTestB4(b)) +unittest(b, hairTestB5(b)) +unittest(b, hairTestB6(b)) +unittest(b, hairTestB7(b)) +unittest(b, hairTestB8(b)) +unittest(b, hairTestB9(b)) +unittest(b, hairTestBA(b)) +unittest(b, hairTestBB(b)) +## enum reference +unittest(b, hairTestBC(b)) + +f <- FirStruct() +b <- "blonde" + +unittest(b, f$hairTestFir1(b)) +unittest(b, f$hairTestFir2(b)) +unittest(b, f$hairTestFir3(b)) +unittest(b, f$hairTestFir4(b)) +unittest(b, f$hairTestFir5(b)) +unittest(b, f$hairTestFir6(b)) +unittest(b, f$hairTestFir7(b)) +unittest(b, f$hairTestFir8(b)) +unittest(b, f$hairTestFir9(b)) +unittest(b, f$hairTestFirA(b)) + +## Unnamed enum instance doesn't work +## Wrapper set/get exists, but there's +## no mapping between strings and integers +GlobalInstance(1) +unittest(1, GlobalInstance()) + +ii <- Instances() +ii$MemberInstance <- 1 +unittest(1, ii$MemberInstance) + +ii <- IgnoreTest() + +## Testing integer values +unittest(0, enumToInteger(IgnoreTest_ignoreA_zero_get(), "_IgnoreTest__IgnoreA")) +unittest(3, enumToInteger(IgnoreTest_ignoreA_three_get(), "_IgnoreTest__IgnoreA")) +unittest(10, enumToInteger(IgnoreTest_ignoreA_ten_get(), "_IgnoreTest__IgnoreA")) + +unittest(11, enumToInteger(IgnoreTest_ignoreA_eleven_get(), "_IgnoreTest__IgnoreA")) +unittest(14, enumToInteger(IgnoreTest_ignoreA_fourteen_get(), "_IgnoreTest__IgnoreA")) +unittest(20, enumToInteger(IgnoreTest_ignoreA_twenty_get(), "_IgnoreTest__IgnoreA")) +unittest(30, enumToInteger(IgnoreTest_ignoreA_thirty_get(), "_IgnoreTest__IgnoreA")) +unittest(32, enumToInteger(IgnoreTest_ignoreA_thirty_two_get(), "_IgnoreTest__IgnoreA")) +unittest(33, enumToInteger(IgnoreTest_ignoreA_thirty_three_get(), "_IgnoreTest__IgnoreA")) + +unittest(11, enumToInteger(IgnoreTest_ignoreB_eleven_get(), "_IgnoreTest__IgnoreB")) +unittest(12, enumToInteger(IgnoreTest_ignoreB_twelve_get(), "_IgnoreTest__IgnoreB")) +unittest(31, enumToInteger(IgnoreTest_ignoreB_thirty_one_get(), "_IgnoreTest__IgnoreB")) +unittest(32, enumToInteger(IgnoreTest_ignoreB_thirty_two_get(), "_IgnoreTest__IgnoreB")) +unittest(41, enumToInteger(IgnoreTest_ignoreB_forty_one_get(), "_IgnoreTest__IgnoreB")) +unittest(42, enumToInteger(IgnoreTest_ignoreB_forty_two_get(), "_IgnoreTest__IgnoreB")) + +unittest(10, enumToInteger(IgnoreTest_ignoreC_ten_get(), "_IgnoreTest__IgnoreC")) +unittest(12, enumToInteger(IgnoreTest_ignoreC_twelve_get(), "_IgnoreTest__IgnoreC")) +unittest(30, enumToInteger(IgnoreTest_ignoreC_thirty_get(), "_IgnoreTest__IgnoreC")) +unittest(32, enumToInteger(IgnoreTest_ignoreC_thirty_two_get(), "_IgnoreTest__IgnoreC")) +unittest(40, enumToInteger(IgnoreTest_ignoreC_forty_get(), "_IgnoreTest__IgnoreC")) +unittest(42, enumToInteger(IgnoreTest_ignoreC_forty_two_get(), "_IgnoreTest__IgnoreC")) + +unittest(21, enumToInteger(IgnoreTest_ignoreD_twenty_one_get(), "_IgnoreTest__IgnoreD")) +unittest(22, enumToInteger(IgnoreTest_ignoreD_twenty_two_get(), "_IgnoreTest__IgnoreD")) + +unittest(0, enumToInteger(IgnoreTest_ignoreE_zero_get(), "_IgnoreTest__IgnoreE")) +unittest(21, enumToInteger(IgnoreTest_ignoreE_twenty_one_get(), "_IgnoreTest__IgnoreE")) +unittest(22, enumToInteger(IgnoreTest_ignoreE_twenty_two_get(), "_IgnoreTest__IgnoreE")) + +## confirm that an ignore directive is followed: +unittest(TRUE, is.na(ignoreCTest("ignoreC_eleven"))) + + +## repeat test +unittest(1, enumToInteger(repeatTest("one"), "_RepeatSpace__repeat")) +unittest(1, enumToInteger(repeatTest("initial"), "_RepeatSpace__repeat")) +unittest(2, enumToInteger(repeatTest("two"), "_RepeatSpace__repeat")) +unittest(3, enumToInteger(repeatTest("three"), "_RepeatSpace__repeat")) +unittest(3, enumToInteger(repeatTest("llast"), "_RepeatSpace__repeat")) +unittest(3, enumToInteger(repeatTest("end"), "_RepeatSpace__repeat")) + +## Macro test - nothing in csharp +## Note - this enum is set up with both entries the same +## This means that mapping back from the integer value to the +## string value isn't unique, so asking for "ABCD2" will return +## a string of "ABCD" +unittest("ABCD", enumWithMacroTest("ABCD")) + +## Different types +unittest(10, enumToInteger(differentTypesTest("typeint"), "_DifferentSpace__DifferentTypes")) +unittest(0, enumToInteger(differentTypesTest("typeboolfalse"), "_DifferentSpace__DifferentTypes")) +unittest(1, enumToInteger(differentTypesTest("typebooltrue"), "_DifferentSpace__DifferentTypes")) +unittest(2, enumToInteger(differentTypesTest("typebooltwo"), "_DifferentSpace__DifferentTypes")) +unittest(utf8ToInt('C'), enumToInteger(differentTypesTest("typechar"), "_DifferentSpace__DifferentTypes")) +unittest(utf8ToInt('D'), enumToInteger(differentTypesTest("typedefaultint"), "_DifferentSpace__DifferentTypes")) +unittest(utf8ToInt('A') + 1, enumToInteger(differentTypesTest("typecharcompound"), "_DifferentSpace__DifferentTypes")) + + +## Global different types +## Test uses an anonymous type so the string mapping +## framework doesn't exist. diff --git a/Examples/test-suite/r/overload_null_runme.R b/Examples/test-suite/r/overload_null_runme.R new file mode 100644 index 000000000..d187a1fbb --- /dev/null +++ b/Examples/test-suite/r/overload_null_runme.R @@ -0,0 +1,49 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + +dyn.load(paste("overload_null", .Platform$dynlib.ext, sep="")) +source("overload_null.R") +cacheMetaData(1) + +o <- Overload() +x <- X() + +unittest(1, o$byval1(x)) +unittest(2, o$byval1(NULL)) + +unittest(3, o$byval2(NULL)) +unittest(4, o$byval2(x)) + +unittest(5, o$byref1(x)) +unittest(6, o$byref1(NULL)) + +unittest(7, o$byref2(NULL)) +unittest(8, o$byref2(x)) + +unittest(9, o$byconstref1(x)) +unittest(10, o$byconstref1(NULL)) + +unittest(11, o$byconstref2(NULL)) +unittest(12, o$byconstref2(x)) + +# const pointer references +# No SWIGTYPE *const& typemaps for R yet +#unittest(13, o$byval1cpr(x)) +#unittest(14, o$byval1cpr(NULL)) + +#unittest(15, o$byval2cpr(NULL)) +#unittest(16, o$byval2cpr(x)) + +# forward class declaration +unittest(17, o$byval1forwardptr(x)) +unittest(18, o$byval1forwardptr(NULL)) + +unittest(19, o$byval2forwardptr(NULL)) +unittest(20, o$byval2forwardptr(x)) + +unittest(21, o$byval1forwardref(x)) + +unittest(22, o$byval2forwardref(x)) + +q(save="no") + diff --git a/Examples/test-suite/r/r_use_isnull_runme.R b/Examples/test-suite/r/r_use_isnull_runme.R new file mode 100644 index 000000000..0dbf8762f --- /dev/null +++ b/Examples/test-suite/r/r_use_isnull_runme.R @@ -0,0 +1,11 @@ +clargs <- commandArgs(trailing=TRUE) +source(file.path(clargs[1], "unittest.R")) + +dyn.load(paste("r_use_isnull", .Platform$dynlib.ext, sep="")) +source("r_use_isnull.R") +cacheMetaData(1) + +tp <- pointerTest() +circ1 <- tp$getCircle(1) +circ1 +unittest(is.null(circ1), TRUE) diff --git a/Examples/test-suite/r_overload_comma.i b/Examples/test-suite/r_overload_comma.i new file mode 100644 index 000000000..020adb387 --- /dev/null +++ b/Examples/test-suite/r_overload_comma.i @@ -0,0 +1,14 @@ +%module r_overload_comma + +%inline %{ +class r_overload_comma +{ + public: + int getMember1()const {return _member1;} + void setMember1ThatEndsWithWord_get(int arg) { _member1=arg; } + void setMember1ThatEndsWithWord_get(char* arg) {_member1=atoi(arg);} + + private: + int _member1; +}; + %} diff --git a/Examples/test-suite/r_use_isnull.i b/Examples/test-suite/r_use_isnull.i new file mode 100644 index 000000000..03b4c15a7 --- /dev/null +++ b/Examples/test-suite/r_use_isnull.i @@ -0,0 +1,34 @@ +%module r_use_isnull + +%inline %{ +// C++ code +class circle { +public: +circle(double radius) +{ +m_radius = radius; +} +double getArea() const +{ +return (3.14 * m_radius * m_radius); +} + +private: +double m_radius; +}; + +class pointerTest { +public: +pointerTest() : m_circle(2) {} +const circle * getCircle(int index) const { +if (index == 0) +return & m_circle; +else +return 0; +} + +private: + circle m_circle; + +}; + %} diff --git a/Examples/test-suite/redefined_not.i b/Examples/test-suite/redefined_not.i index db9d3a248..fde5994fb 100644 --- a/Examples/test-suite/redefined_not.i +++ b/Examples/test-suite/redefined_not.i @@ -1,6 +1,6 @@ %module redefined_not -// These should not emit an Identifer redefined warning +// These should not emit an Identifier redefined warning %inline %{ typedef unsigned int my_size_t; namespace Std { diff --git a/Examples/test-suite/register_par.i b/Examples/test-suite/register_par.i index 030be4556..643841455 100644 --- a/Examples/test-suite/register_par.i +++ b/Examples/test-suite/register_par.i @@ -1,6 +1,10 @@ %module register_par +%{ +struct swig_tree; +%} + // bug # 924413 %inline { - void clear_tree_flags(register struct tree *tp, register int i) {} + void clear_tree_flags(register struct swig_tree *tp, register int i) {} } diff --git a/Examples/test-suite/rename.h b/Examples/test-suite/rename.h index c8199eeeb..3f10c5856 100644 --- a/Examples/test-suite/rename.h +++ b/Examples/test-suite/rename.h @@ -27,7 +27,6 @@ namespace Space { void templateXYZ(XYZ i) {} operator T() { return m_t; } operator NotXYZ() const { return m_notxyz; } - operator XYZ() const { XYZ xyz = XYZ(); return xyz; } }; } @@ -48,10 +47,7 @@ class ABC { public: void method(ABC a) const {} void method(Klass k) const {} -#if !defined(__clang__) - // Workaround for: warning: conversion function converting 'Space::ABC' to itself will never be used - operator ABC() const { ABC a; return a; } -#endif + operator ABC*() const { return new ABC(); } operator Klass() const { Klass k; return k; } }; } diff --git a/Examples/test-suite/rename1.i b/Examples/test-suite/rename1.i index 38af2b3bd..92e6b3494 100644 --- a/Examples/test-suite/rename1.i +++ b/Examples/test-suite/rename1.i @@ -35,14 +35,9 @@ %rename(opNotXYZ3) Space::XYZ::operator NotXYZ() const; %rename(opNotXYZ4) Space::XYZ::operator NotXYZ() const; -%rename(opXYZ1) Space::XYZ::operator XYZ() const; -%rename(opXYZ2) Space::XYZ::operator XYZ() const; -%rename(opXYZ3) Space::XYZ::operator XYZ() const; -%rename(opXYZ4) Space::XYZ::operator XYZ() const; - %rename(methodABC) Space::ABC::method(ABC a) const; -%rename(opABC) Space::ABC::operator ABC() const; +%rename(opABC) Space::ABC::operator ABC*() const; %rename(methodKlass) Space::ABC::method(Klass k) const; %rename(opKlass) Space::ABC::operator Klass() const; diff --git a/Examples/test-suite/rename2.i b/Examples/test-suite/rename2.i index 6a9c22ecf..93b82ddc6 100644 --- a/Examples/test-suite/rename2.i +++ b/Examples/test-suite/rename2.i @@ -43,7 +43,7 @@ namespace Space { %rename(methodABC) ABC::method(ABC a) const; -%rename(opABC) ABC::operator ABC() const; +%rename(opABC) ABC::operator ABC*() const; %rename(methodKlass) ABC::method(Klass k) const; %rename(opKlass) ABC::operator Klass() const; } diff --git a/Examples/test-suite/rename3.i b/Examples/test-suite/rename3.i index b39979fdd..5b613d769 100644 --- a/Examples/test-suite/rename3.i +++ b/Examples/test-suite/rename3.i @@ -52,7 +52,7 @@ namespace Space { %extend ABC { %rename(methodABC) method(ABC a) const; - %rename(opABC) operator ABC() const; + %rename(opABC) operator ABC*() const; %rename(methodKlass) method(Klass k) const; %rename(opKlass) operator Klass() const; } diff --git a/Examples/test-suite/rename4.i b/Examples/test-suite/rename4.i index 9ddff362f..75f01ca5b 100644 --- a/Examples/test-suite/rename4.i +++ b/Examples/test-suite/rename4.i @@ -29,21 +29,18 @@ namespace Space { %rename(tMethodXYZ2) templateXYZ(XYZ); %rename(opT2) operator int(); %rename(opNotXYZ2) operator NotXYZ() const; -%rename(opXYZ2) operator XYZ() const; %rename(tMethod3) templateT(Space::Klass i); %rename(tMethodNotXYZ3) templateNotXYZ(NotXYZ); %rename(tMethodXYZ3) templateXYZ(XYZ); %rename(opT3) operator Space::Klass(); %rename(opNotXYZ3) operator NotXYZ() const; -%rename(opXYZ3) operator XYZ() const; %rename(tMethod4) templateT(Space::Enu i); %rename(tMethodNotXYZ4) templateNotXYZ(NotXYZ); %rename(tMethodXYZ4) templateXYZ(XYZ); %rename(opT4) operator Space::Enu(); %rename(opNotXYZ4) operator NotXYZ() const; -%rename(opXYZ4) operator XYZ() const; namespace Space { using namespace AnotherSpace; @@ -60,7 +57,6 @@ namespace Space { %rename(tMethodXYZ1) templateXYZ(XYZ); %rename(opT1) operator T(); %rename(opNotXYZ1) operator NotXYZ() const; - %rename(opXYZ1) operator XYZ() const; NotXYZ *m_int; T m_t; @@ -74,7 +70,6 @@ namespace Space { void templateXYZ(XYZ i) {} operator T() { return m_t; } operator NotXYZ() const { return m_notxyz; } - operator XYZ() const { XYZ xyz; return xyz; } }; } @@ -93,16 +88,13 @@ class ABC { public: %rename(methodABC) method(ABC a) const; - %rename(opABC) operator ABC() const; + %rename(opABC) operator ABC*() const; %rename(methodKlass) method(Klass k) const; %rename(opKlass) operator Klass() const; void method(ABC a) const {} void method(Klass k) const {} -#if !defined(__clang__) - // Workaround for: warning: conversion function converting 'Space::ABC' to itself will never be used - operator ABC() const { ABC a; return a; } -#endif + operator ABC*() const { return new ABC(); } operator Klass() const { Klass k; return k; } }; } diff --git a/Examples/test-suite/rename_wildcard.i b/Examples/test-suite/rename_wildcard.i new file mode 100644 index 000000000..f9e0347b0 --- /dev/null +++ b/Examples/test-suite/rename_wildcard.i @@ -0,0 +1,140 @@ +// Test rename overriding a wildcard rename +%module rename_wildcard + +%rename(mm1) *::m1; +%rename(mm2) *::m2; +%rename(tt2) *::t2; +%rename(mm3) *::m3(); +%rename(tt3) *::t3(); +%rename(m_4) m4; +%rename(t_4) t4; +%rename(mm4) *::m4; +%rename(tt4) *::t4; +%rename(mm5) *::m5; +%rename(tt5) *::t5; +%rename(opint) *::operator int; +%rename(opdouble) *::operator double; + +// No declaration +%rename(mm2a) GlobalWildStruct::m2; +%rename(mm2b) GlobalWildTemplateStruct::m2; +%rename(mm2c) Space::SpaceWildStruct::m2; +%rename(mm2d) Space::SpaceWildTemplateStruct::m2; +%rename(tt2b) GlobalWildTemplateStruct::t2; +%rename(tt2d) Space::SpaceWildTemplateStruct::t2; + +// With declaration +%rename(mm3a) GlobalWildStruct::m3; +%rename(mm3b) GlobalWildTemplateStruct::m3; +%rename(mm3c) Space::SpaceWildStruct::m3; +%rename(mm3d) Space::SpaceWildTemplateStruct::m3; +%rename(tt3b) GlobalWildTemplateStruct::t3; +%rename(tt3d) Space::SpaceWildTemplateStruct::t3; + +// Global override too +%rename(mm4a) GlobalWildStruct::m4; +%rename(mm4b) GlobalWildTemplateStruct::m4; +%rename(mm4c) Space::SpaceWildStruct::m4; +%rename(mm4d) Space::SpaceWildTemplateStruct::m4; +%rename(tt4b) GlobalWildTemplateStruct::t4; +%rename(tt4d) Space::SpaceWildTemplateStruct::t4; + +// %extend renames +%extend GlobalWildStruct { + %rename(mm5a) m5; +} +%extend GlobalWildTemplateStruct { + %rename(mm5b) m5; +} +%extend GlobalWildTemplateStruct { + %rename(tt5b) t5; +} +namespace Space { + %extend SpaceWildStruct { + %rename(mm5c) m5; + } + %extend SpaceWildTemplateStruct { + %rename(mm5d) m5; + } + %extend SpaceWildTemplateStruct { + %rename(tt5d) t5; + } +} + +// operators +%rename(opinta) GlobalWildStruct::operator int; +%rename(opintb) GlobalWildTemplateStruct::operator int; +%rename(opintc) Space::SpaceWildStruct::operator int; +%rename(opintd) Space::SpaceWildTemplateStruct::operator int; +%rename(opdoubleb) GlobalWildTemplateStruct::operator double; +%rename(opdoubled) Space::SpaceWildTemplateStruct::operator double; + +%inline %{ +struct GlobalWildStruct { + void m1() {} + void m2() {} + void m3() {} + void m4() {} + void m5() {} + operator int() { return 0; } +}; +template struct GlobalWildTemplateStruct { + void m1() {} + void m2() {} + void t2() {} + void m3() {} + void t3() {} + void m4() {} + void t4() {} + void m5() {} + void t5() {} + operator int() { return 0; } + operator double() { return 0.0; } +}; +namespace Space { + struct SpaceWildStruct { + void m1() {} + void m2() {} + void m3() {} + void m4() {} + void m5() {} + operator int() { return 0; } + }; + template struct SpaceWildTemplateStruct { + void m1() {} + void m2() {} + void t2() {} + void m3() {} + void t3() {} + void m4() {} + void t4() {} + void m5() {} + void t5() {} + operator int() { return 0; } + operator double() { return 0.0; } + }; +} + +// Wild card renames expected for these +struct NoChangeStruct { + void m1() {} + void m2() {} + void m3() {} + void m4() {} + void m5() {} + operator int() { return 0; } +}; +namespace Space { + struct SpaceNoChangeStruct { + void m1() {} + void m2() {} + void m3() {} + void m4() {} + void m5() {} + operator int() { return 0; } + }; +} +%} + +%template(GlobalWildTemplateStructInt) GlobalWildTemplateStruct; +%template(SpaceWildTemplateStructInt) Space::SpaceWildTemplateStruct; diff --git a/Examples/test-suite/restrict_cplusplus.i b/Examples/test-suite/restrict_cplusplus.i index 62abffa52..53c5782a1 100644 --- a/Examples/test-suite/restrict_cplusplus.i +++ b/Examples/test-suite/restrict_cplusplus.i @@ -1,7 +1,8 @@ %module restrict_cplusplus %{ -// For PHP 5.3 / gcc-4.4 +// Workaround PHP's headers which do: +// #define restrict __restrict__ #ifdef restrict #undef restrict #endif diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index d94ac7061..d75cdb058 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -14,23 +14,40 @@ CPP_TEST_CASES = \ li_cstring \ li_factory \ li_std_functors \ + li_std_list \ li_std_multimap \ li_std_pair_lang_object \ li_std_queue \ li_std_set \ li_std_stack \ + li_std_wstring_inherit \ primitive_types \ + ruby_alias_method \ ruby_keywords \ ruby_minherit_shared_ptr \ ruby_naming \ + ruby_rdata \ ruby_track_objects \ ruby_track_objects_directors \ - std_containers -# ruby_li_std_speed -# stl_new + std_containers \ +# ruby_li_std_speed \ +# stl_new \ + +CPP11_TEST_CASES = \ + cpp11_hash_tables \ + cpp11_shared_ptr_const \ + cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ + cpp11_shared_ptr_upcast \ + cpp11_std_unordered_map \ + cpp11_std_unordered_multimap \ + cpp11_std_unordered_multiset \ + cpp11_std_unordered_set \ C_TEST_CASES += \ li_cstring \ + ruby_alias_global_function \ + ruby_alias_module_function \ ruby_manual_proxy \ include $(srcdir)/../common.mk @@ -39,6 +56,7 @@ include $(srcdir)/../common.mk SWIGOPT += -w801 -noautorename -features autodoc=4 # Custom tests - tests with additional commandline options +ruby_alias_global_function.ctest: SWIGOPT += -globalmodule ruby_naming.cpptest: SWIGOPT += -autorename # Rules for the different types of tests diff --git a/Examples/test-suite/ruby/cpp11_hash_tables_runme.rb b/Examples/test-suite/ruby/cpp11_hash_tables_runme.rb new file mode 100644 index 000000000..203b0ce06 --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_hash_tables_runme.rb @@ -0,0 +1,61 @@ +require 'swig_assert' +require 'cpp11_hash_tables' + +[Cpp11_hash_tables::MapIntInt.new({1=>7}), + Cpp11_hash_tables::MultiMapIntInt.new({1=>7}), + Cpp11_hash_tables::UnorderedMapIntInt.new({1=>7}), + Cpp11_hash_tables::UnorderedMultiMapIntInt.new({1=>7})].each{|x| + + swig_assert_equal("x.find_all{|e,k| e == 1}", "[[1,7]]", binding) + + swig_assert_equal("x[1]", "7", binding) + swig_assert_equal("x[2]", "nil", binding) + x[2] = 9 + swig_assert_equal("x[2]", "9", binding) + x.delete(2) + swig_assert_equal("x[2]", "nil", binding) + swig_assert_equal("x.empty?", "false", binding) + x.delete(1) + swig_assert_equal("x.empty?", "true", binding) + swig_assert_equal("x.include?(1)", "false", binding) +} + +[Cpp11_hash_tables::MultiMapIntInt.new({1=>7}), + Cpp11_hash_tables::UnorderedMultiMapIntInt.new({1=>7})].each{|x| + x[1] = 9 + swig_assert_equal("x[1].sort", "[7,9]", binding) +} + +[Cpp11_hash_tables::SetInt.new([1]), + Cpp11_hash_tables::MultiSetInt.new([1]), + Cpp11_hash_tables::UnorderedSetInt.new([1]), + Cpp11_hash_tables::UnorderedMultiSetInt.new([1])].each{|x| + + swig_assert_equal("x.find_all{|e| e == 1}", "[1]", binding) + + swig_assert_equal("x.include?(1)", "true", binding) + swig_assert_equal("x.include?(2)", "false", binding) + x << 2 + swig_assert_equal("x.include?(2)", "true", binding) + x.erase(2) + swig_assert_equal("x.empty?", "false", binding) + x.erase(1) + swig_assert_equal("x.empty?", "true", binding) +} + +[Cpp11_hash_tables::MultiSetInt.new([1]), + Cpp11_hash_tables::UnorderedMultiSetInt.new([1])].each{|x| + x << 1 + swig_assert_equal("x.count(1)", "2", binding) +} + +[Cpp11_hash_tables::MapIntInt, + Cpp11_hash_tables::MultiMapIntInt, + Cpp11_hash_tables::UnorderedMapIntInt, + Cpp11_hash_tables::UnorderedMultiMapIntInt, + Cpp11_hash_tables::SetInt, + Cpp11_hash_tables::MultiSetInt, + Cpp11_hash_tables::UnorderedSetInt, + Cpp11_hash_tables::UnorderedMultiSetInt].each{|k| + swig_assert("k.include?(Enumerable)", binding) +} diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb new file mode 100644 index 000000000..149aa0898 --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb @@ -0,0 +1,9 @@ +require "swig_assert" +require "cpp11_shared_ptr_const" + +include Cpp11_shared_ptr_const + +swig_assert_equal_simple(1, foo( Foo.new(1) ).get_m ) +swig_assert_equal_simple(7, const_foo( Foo.new(7) ).get_m ) +swig_assert_equal_simple(7, foo_vec( Foo.new(7) )[0].get_m ) +swig_assert_equal_simple(8, const_foo_vec( Foo.new(8) )[0].get_m ) diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb new file mode 100644 index 000000000..9d8b3c050 --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb @@ -0,0 +1,16 @@ +require "cpp11_shared_ptr_nullptr_in_containers" + +include Cpp11_shared_ptr_nullptr_in_containers + +a = ret_vec_c_shared_ptr() +raise unless a[0].get_m == 0 +raise unless a[1] == nil +raise unless a[2].get_m == 2 + +a = ret_arg_vec([C.new(7), nil, C.new(9)]) +raise unless a[0].get_m == 7 +raise unless a[1] == nil +raise unless a[2].get_m == 9 + +raise unless is_last_null([C.new(7), C.new(8), nil]) +raise if is_last_null([C.new(7), C.new(8)]) diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb new file mode 100644 index 000000000..000b9b6a9 --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb @@ -0,0 +1,60 @@ +require 'swig_assert' +require 'cpp11_shared_ptr_upcast' + + +include Cpp11_shared_ptr_upcast + +# non-overloaded +swig_assert_equal_simple( 7, derived_num1(Derived.new(7)) ) +swig_assert_equal_simple( 7, derived_num2([Derived.new(7)]) ) +swig_assert_equal_simple( 7, derived_num3({0 => Derived.new(7)}) ) + +swig_assert_equal_simple(-1, base_num1(Derived.new(7)) ) +swig_assert_equal_simple(-1, base_num2([Derived.new(7)]) ) +swig_assert_equal_simple(-1, base_num3({0 => Derived.new(7)}) ) + +swig_assert_equal_simple( 999, derived_num1(nil) ) +swig_assert_equal_simple( 999, derived_num2([nil]) ) +swig_assert_equal_simple( 999, derived_num3({0 => nil}) ) + +swig_assert_equal_simple( 999, base_num1(nil) ) +swig_assert_equal_simple( 999, base_num2([nil]) ) +swig_assert_equal_simple( 999, base_num3({0 => nil}) ) + +# overloaded +swig_assert_equal_simple( 7, derived_num(Derived.new(7)) ) +swig_assert_equal_simple( 7, derived_num([Derived.new(7)]) ) +swig_assert_equal_simple( 7, derived_num({0 => Derived.new(7)}) ) + +swig_assert_equal_simple(-1, base_num(Derived.new(7)) ) +swig_assert_equal_simple(-1, base_num([Derived.new(7)]) ) +swig_assert_equal_simple(-1, base_num({0 => Derived.new(7)}) ) + +# ptr to shared_ptr +swig_assert_equal_simple( 7, derived2_num1(Derived2.new(7)) ) +swig_assert_equal_simple( 7, derived2_num2([Derived2.new(7)]) ) +swig_assert_equal_simple( 7, derived2_num3({0 => Derived2.new(7)}) ) + +swig_assert_equal_simple( -1, base2_num1(Derived2.new(7)) ) + +begin + # Upcast for pointers to shared_ptr in this generic framework has not been implemented + swig_assert_equal_simple( -1, base2_num2([Derived2.new(7)]) ) + raise RuntimeError, "Failed to catch TypeError" +rescue TypeError +end +begin + # Upcast for pointers to shared_ptr in this generic framework has not been implemented + swig_assert_equal_simple( -1, base2_num3({0 => Derived2.new(7)}) ) + raise RuntimeError, "Failed to catch TypeError" +rescue TypeError +end + +swig_assert_equal_simple( 888, derived2_num1(nil) ) +swig_assert_equal_simple( 999, derived2_num2([nil]) ) # although 888 would be more consistent +swig_assert_equal_simple( 999, derived2_num3({0 => nil}) ) # although 888 would be more consistent + +swig_assert_equal_simple( 888, base2_num1(nil) ) +swig_assert_equal_simple( 999, base2_num2([nil]) ) # although 888 would be more consistent +swig_assert_equal_simple( 999, base2_num3({0 => nil}) ) # although 888 would be more consistent + diff --git a/Examples/test-suite/ruby/cpp11_li_std_array_runme.rb b/Examples/test-suite/ruby/cpp11_std_array_runme.rb similarity index 98% rename from Examples/test-suite/ruby/cpp11_li_std_array_runme.rb rename to Examples/test-suite/ruby/cpp11_std_array_runme.rb index 770f37c0f..13c5efb84 100644 --- a/Examples/test-suite/ruby/cpp11_li_std_array_runme.rb +++ b/Examples/test-suite/ruby/cpp11_std_array_runme.rb @@ -9,9 +9,9 @@ require 'swig_assert' -require 'cpp11_li_std_array' +require 'cpp11_std_array' -include Cpp11_li_std_array +include Cpp11_std_array def failed(a, b, msg) diff --git a/Examples/test-suite/ruby/director_smartptr_runme.rb b/Examples/test-suite/ruby/director_smartptr_runme.rb index 8b4bd3d6d..46ef8b1b5 100644 --- a/Examples/test-suite/ruby/director_smartptr_runme.rb +++ b/Examples/test-suite/ruby/director_smartptr_runme.rb @@ -30,6 +30,25 @@ class Director_smartptr_MyBarFoo < Foo end end +class Director_smartptr_MyBarFooDerived < FooDerived + + def ping() + return "director_smartptr_MyBarFooDerived.ping()" + end + + def pong() + return "director_smartptr_MyBarFooDerived.pong();" + ping() + end + + def upcall(fooBarPtr) + return "overrideDerived;" + fooBarPtr.FooBarDo() + end + + def makeFoo() + return Foo.new() + end +end + def check(got, expected) if (got != expected) raise RuntimeError, "Failed, got: #{got} expected: #{expected}" @@ -52,3 +71,8 @@ myFoo2 = Foo.new().makeFoo() check(myFoo2.pong(), "Foo::pong();Foo::ping()") check(Foo.callPong(myFoo2), "Foo::pong();Foo::ping()") check(myFoo2.upcall(FooBar.new()), "Bar::Foo2::Foo2Bar()") + +myBarFooDerived = Director_smartptr_MyBarFooDerived.new() +check(myBarFooDerived.ping(), "director_smartptr_MyBarFooDerived.ping()") +check(FooDerived.callPong(myBarFooDerived), "director_smartptr_MyBarFooDerived.pong();director_smartptr_MyBarFooDerived.ping()") +check(FooDerived.callUpcall(myBarFooDerived, fooBar), "overrideDerived;Bar::Foo2::Foo2Bar()") diff --git a/Examples/test-suite/ruby/li_boost_array_runme.rb b/Examples/test-suite/ruby/li_boost_array_runme.rb deleted file mode 100644 index a7b7720ea..000000000 --- a/Examples/test-suite/ruby/li_boost_array_runme.rb +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env ruby -# -# Put description here -# -# -# -# -# - -require 'swig_assert' - -require 'li_boost_array' - -include Li_boost_array - - -def failed(a, b, msg) - raise RuntimeError, "#{msg} #{a} #{b}" -end - -def compare_sequences(a, b) - if a.size != b.size - failed(a, b, "different sizes") - end - for i in 0..a.size-1 - failed(a, b, "elements are different:") if a[i] != b[i] - end -end - -def compare_containers(rubyarray, swigarray) - compare_sequences(rubyarray, swigarray) -end - -ps = [0, 1, 2, 3, 4, 5] - -ai = ArrayInt6.new(ps) - -compare_containers(ps, ai) - -# Modify content -for i in 0..ps.size-1 - ps[i] = ps[i] * 10 - ai[i] = ai[i] * 10 -end -compare_containers(ps, ai) - -# Empty -ai = ArrayInt6.new() - -# Check return -compare_containers(arrayOutVal(), [-2, -1, 0, 0, 1, 2]) -compare_containers(arrayOutConstRef(), [-2, -1, 0, 0, 1, 2]) -#compare_containers(arrayOutRef(), [-2, -1, 0, 0, 1, 2]) -#compare_containers(arrayOutPtr(), [-2, -1, 0, 0, 1, 2]) - -# Check passing arguments -ai = arrayInVal([9, 8, 7, 6, 5, 4]) -compare_containers(ai, [90, 80, 70, 60, 50, 40]) - -ai = arrayInConstRef([9, 8, 7, 6, 5, 4]) -compare_containers(ai, [90, 80, 70, 60, 50, 40]) - -#ai = ArrayInt6.new([9, 8, 7, 6, 5, 4]) -#arrayInRef(ai) -#compare_containers(ai, [90, 80, 70, 60, 50, 40]) - -#ai = ArrayInt6.new([9, 8, 7, 6, 5, 4]) -#arrayInPtr(ai) -#compare_containers(ai, [90, 80, 70, 60, 50, 40]) - diff --git a/Examples/test-suite/ruby/li_boost_shared_ptr_director_runme.rb b/Examples/test-suite/ruby/li_boost_shared_ptr_director_runme.rb new file mode 100644 index 000000000..55c1cbebd --- /dev/null +++ b/Examples/test-suite/ruby/li_boost_shared_ptr_director_runme.rb @@ -0,0 +1,103 @@ +require 'li_boost_shared_ptr_director' + +include Li_boost_shared_ptr_director + +class Derived < Base + + def initialize(flag) + @return_none = flag + super() + end + + def ret_c_shared_ptr + if @return_none + nil + else + C.new + end + end + + def ret_c_by_value + C.new + end + + def take_c_by_value(c) + c.get_m + end + + def take_c_by_ref(c) + c.get_m + end + + def take_c_by_pointer(c) + if c + c.get_m + else + -2 + end + end + + def take_c_by_pointer_ref(c) + if c + c.get_m + else + -3 + end + end + + def take_c_shared_ptr_by_value(c) + if c + c.get_m + else + -4 + end + end + + def take_c_shared_ptr_by_ref(c) + if c + c.get_m + else + -5 + end + end + + def take_c_shared_ptr_by_pointer(c) + if c + c.get_m + else + -6 + end + end + + def take_c_shared_ptr_by_pointer_ref(c) + if c + c.get_m + else + -7 + end + end + +end + +a = Derived.new(false) +b = Derived.new(true) + +raise unless call_ret_c_shared_ptr(a) == 1 +raise unless call_ret_c_shared_ptr(b) == -1 +raise unless call_ret_c_by_value(a) == 1 + +raise unless call_take_c_by_value(a) == 5 +raise unless call_take_c_by_ref(a) == 6 +raise unless call_take_c_by_pointer(a) == 7 +raise unless call_take_c_by_pointer_ref(a) == 8 +raise unless call_take_c_shared_ptr_by_value(a) == 9 +raise unless call_take_c_shared_ptr_by_ref(a) == 10 +raise unless call_take_c_shared_ptr_by_pointer(a) == 11 +raise unless call_take_c_shared_ptr_by_pointer_ref(a) == 12 + +raise unless call_take_c_by_pointer_with_null(a) == -2 +raise unless call_take_c_by_pointer_ref_with_null(a) == -3 +raise unless call_take_c_shared_ptr_by_value_with_null(a) == -4 +raise unless call_take_c_shared_ptr_by_ref_with_null(a) == -5 +raise unless call_take_c_shared_ptr_by_pointer_with_null(a) == -6 +raise unless call_take_c_shared_ptr_by_pointer_ref_with_null(a) == -7 diff --git a/Examples/test-suite/ruby/li_std_list_runme.rb b/Examples/test-suite/ruby/li_std_list_runme.rb new file mode 100644 index 000000000..b1182e2e3 --- /dev/null +++ b/Examples/test-suite/ruby/li_std_list_runme.rb @@ -0,0 +1,8 @@ +require 'swig_assert' + +require 'li_std_list' + +include Li_std_list + +x = DoubleList.new([1,2,3]) +swig_assert_equal("[1.0]", "x.find_all{|e| e == 1 }", binding) diff --git a/Examples/test-suite/ruby/li_std_wstring_inherit_runme.rb b/Examples/test-suite/ruby/li_std_wstring_inherit_runme.rb new file mode 100644 index 000000000..b5a90d834 --- /dev/null +++ b/Examples/test-suite/ruby/li_std_wstring_inherit_runme.rb @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +require 'swig_assert' +require 'li_std_wstring_inherit' +x = "abc" +swig_assert_equal("Li_std_wstring_inherit.test_value(Li_std_wstring_inherit::Wstring.new(x))", "x", binding) + + +x = "y" +swig_assert_equal("Li_std_wstring_inherit.test_value(x)", "x", binding) +a = Li_std_wstring_inherit::A.new(x) +swig_assert_equal("Li_std_wstring_inherit.test_value(a)", "x", binding) + diff --git a/Examples/test-suite/ruby/li_std_wstring_runme.rb b/Examples/test-suite/ruby/li_std_wstring_runme.rb new file mode 100644 index 000000000..4922d8d90 --- /dev/null +++ b/Examples/test-suite/ruby/li_std_wstring_runme.rb @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +require 'swig_assert' +require 'li_std_wstring' + +h = "h" +swig_assert_equal("Li_std_wstring.test_wcvalue(h)", "h", binding) + +x = "abc" +swig_assert_equal("Li_std_wstring.test_ccvalue(x)", "x", binding) +swig_assert_equal("Li_std_wstring.test_cvalue(x)", "x", binding) + +swig_assert_equal("Li_std_wstring.test_wchar_overload(x)", "x", binding) +swig_assert_equal("Li_std_wstring.test_wchar_overload()", "nil", binding) + +Li_std_wstring.test_pointer(nil) +Li_std_wstring.test_const_pointer(nil) + +begin + Li_std_wstring.test_value(nil) + raise RuntimeError, "NULL check failed" +rescue TypeError => e +end + +begin + Li_std_wstring.test_reference(nil) + raise RuntimeError, "NULL check failed" +rescue ArgumentError => e + swig_assert_simple(e.message.include? "invalid null reference") +end +begin + Li_std_wstring.test_const_reference(nil) + raise RuntimeError, "NULL check failed" +rescue ArgumentError => e + swig_assert_simple(e.message.include? "invalid null reference") +end + +x = "hello" +swig_assert_equal("Li_std_wstring.test_const_reference(x)", "x", binding) + +s = "abc" +swig_assert("Li_std_wstring.test_equal_abc(s)", binding) + +begin + Li_std_wstring.test_throw +rescue RuntimeError => e + swig_assert_equal("e.message", "'throwing test_throw'", binding) +end + +x = "abc\0def" +swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) +swig_assert_equal("Li_std_wstring.test_ccvalue(x)", '"abc"', binding) +swig_assert_equal("Li_std_wstring.test_wchar_overload(x)", '"abc"', binding) diff --git a/Examples/test-suite/ruby/newobject1_runme.rb b/Examples/test-suite/ruby/newobject1_runme.rb index f5dc12fb5..be1949377 100644 --- a/Examples/test-suite/ruby/newobject1_runme.rb +++ b/Examples/test-suite/ruby/newobject1_runme.rb @@ -8,7 +8,7 @@ # # Ruby's GC is somewhat broken in that it will mark some more stack space # leading to the collection of local objects to be delayed. -# Thus, upon invokation, it sometimes you can wait up to several +# Thus, upon invocation, it sometimes you can wait up to several # instructions to kick in. # See: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/7449 # diff --git a/Examples/test-suite/ruby/newobject2_runme.rb b/Examples/test-suite/ruby/newobject2_runme.rb index 99bc24374..04129f4aa 100644 --- a/Examples/test-suite/ruby/newobject2_runme.rb +++ b/Examples/test-suite/ruby/newobject2_runme.rb @@ -2,7 +2,7 @@ # # Ruby's GC is somewhat broken in that it will mark some more stack space # leading to the collection of local objects to be delayed. -# Thus, upon invokation, it sometimes you can wait up to several +# Thus, upon invocation, it sometimes you can wait up to several # instructions to kick in. # See: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/7449 # diff --git a/Examples/test-suite/ruby/overload_null_runme.rb b/Examples/test-suite/ruby/overload_null_runme.rb new file mode 100644 index 000000000..eabea5e40 --- /dev/null +++ b/Examples/test-suite/ruby/overload_null_runme.rb @@ -0,0 +1,52 @@ +#!/usr/bin/env ruby +# +# Put script description here. +# +# +# +# +# + +require 'swig_assert' +require 'overload_null' + +include Overload_null + +o = Overload.new +x = X.new + +swig_assert(1 == o.byval1(x)) +swig_assert(2 == o.byval1(nil)) + +swig_assert(3 == o.byval2(nil)) +swig_assert(4 == o.byval2(x)) + +swig_assert(5 == o.byref1(x)) +swig_assert(6 == o.byref1(nil)) + +swig_assert(7 == o.byref2(nil)) +swig_assert(8 == o.byref2(x)) + +swig_assert(9 == o.byconstref1(x)) +swig_assert(10 == o.byconstref1(nil)) + +swig_assert(11 == o.byconstref2(nil)) +swig_assert(12 == o.byconstref2(x)) + +# const pointer references +swig_assert(13 == o.byval1cpr(x)) +swig_assert(14 == o.byval1cpr(nil)) + +swig_assert(15 == o.byval2cpr(nil)) +swig_assert(16 == o.byval2cpr(x)) + +# forward class declaration +swig_assert(17 == o.byval1forwardptr(x)) +swig_assert(18 == o.byval1forwardptr(nil)) + +swig_assert(19 == o.byval2forwardptr(nil)) +swig_assert(20 == o.byval2forwardptr(x)) + +swig_assert(21 == o.byval1forwardref(x)) + +swig_assert(22 == o.byval2forwardref(x)) diff --git a/Examples/test-suite/ruby/ruby_alias_global_function_runme.rb b/Examples/test-suite/ruby/ruby_alias_global_function_runme.rb new file mode 100644 index 000000000..14e38e4cf --- /dev/null +++ b/Examples/test-suite/ruby/ruby_alias_global_function_runme.rb @@ -0,0 +1,20 @@ +#!/usr/bin/env ruby +# +# Runtime tests for ruby_alias_global_function.i +# + +require 'swig_assert' +require 'ruby_alias_global_function' + +expected_name = get_my_name + +swig_assert(fullname == expected_name, msg: "nickname not working as expected") +swig_assert(nickname == expected_name, msg: "fullname not working as expected") + +if method(:nickname).respond_to?(:original_name) + swig_assert_equal_simple(method(:nickname).original_name, :get_my_name) + swig_assert_equal_simple(method(:fullname).original_name, :get_my_name) +else + swig_assert(method(:nickname) == method(:get_my_name), msg: "nickname is not an alias of get_my_name") + swig_assert(method(:fullname) == method(:get_my_name), msg: "fullname is not an alias of get_my_name") +end diff --git a/Examples/test-suite/ruby/ruby_alias_method_runme.rb b/Examples/test-suite/ruby/ruby_alias_method_runme.rb new file mode 100644 index 000000000..c19101e63 --- /dev/null +++ b/Examples/test-suite/ruby/ruby_alias_method_runme.rb @@ -0,0 +1,24 @@ +#!/usr/bin/env ruby +# +# Runtime tests for ruby_alias_method.i +# + +require 'swig_assert' +require 'ruby_alias_method' + +include Ruby_alias_method + +expected_name = "Chester Tester" +syn = Synonym.new(expected_name) + +swig_assert(syn.getMyName() == expected_name, msg: "getMyName not working as expected") +swig_assert(syn.nickname() == expected_name, msg: "nickname not working as expected") +swig_assert(syn.fullname() == expected_name, msg: "fullname not working as expected") + +if syn.method(:nickname).respond_to?(:original_name) + swig_assert_equal_simple(syn.method(:nickname).original_name, :getMyName) + swig_assert_equal_simple(syn.method(:fullname).original_name, :getMyName) +else + swig_assert(syn.method(:nickname) == syn.method(:getMyName)) + swig_assert(syn.method(:fullname) == syn.method(:getMyName)) +end diff --git a/Examples/test-suite/ruby/ruby_alias_module_function_runme.rb b/Examples/test-suite/ruby/ruby_alias_module_function_runme.rb new file mode 100644 index 000000000..1f4205f1f --- /dev/null +++ b/Examples/test-suite/ruby/ruby_alias_module_function_runme.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +# +# Runtime tests for ruby_alias_module_function.i +# + +require 'swig_assert' +require 'ruby_alias_module_function' + +include Ruby_alias_module_function + +expected_name = Ruby_alias_module_function.get_my_name + +swig_assert(Ruby_alias_module_function.nickname == expected_name, msg: "nickname returned a different result than get_my_name") +swig_assert(Ruby_alias_module_function.fullname == expected_name, msg: "fullname returned a different result than get_my_name") + +nickname_method = Ruby_alias_module_function.method(:nickname) +fullname_method = Ruby_alias_module_function.method(:fullname) + +if nickname_method.respond_to?(:original_name) + swig_assert_equal_simple(nickname_method.original_name, :get_my_name) + swig_assert_equal_simple(fullname_method.original_name, :get_my_name) +else + original_method = Ruby_alias_module_function.method(:get_my_name) + swig_assert(nickname_method == original_method, msg: "nickname is not an alias of get_my_name") + swig_assert(fullname_method == original_method, msg: "fullname is not an alias of get_my_name") +end diff --git a/Examples/test-suite/ruby/ruby_rdata_runme.rb b/Examples/test-suite/ruby/ruby_rdata_runme.rb new file mode 100644 index 000000000..b7f293077 --- /dev/null +++ b/Examples/test-suite/ruby/ruby_rdata_runme.rb @@ -0,0 +1,7 @@ +require 'swig_assert' +require 'ruby_rdata' + +include Ruby_rdata + +swig_assert_equal_simple(1, take_proc_or_cpp_obj_and_ret_1(Proc.new{})) +swig_assert_equal_simple(1, take_proc_or_cpp_obj_and_ret_1(C.new)) diff --git a/Examples/test-suite/ruby/std_containers_runme.rb b/Examples/test-suite/ruby/std_containers_runme.rb index 73d443218..65a8b5b86 100644 --- a/Examples/test-suite/ruby/std_containers_runme.rb +++ b/Examples/test-suite/ruby/std_containers_runme.rb @@ -13,6 +13,8 @@ require 'swig_assert' require 'std_containers' include Std_containers +swig_assert_equal("[true, false]", "videntb([true, false])") + swig_assert_each_line(<<'EOF', binding) cube = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]] diff --git a/Examples/test-suite/ruby/swig_assert.rb b/Examples/test-suite/ruby/swig_assert.rb index 69a1a0207..cbdfc036d 100644 --- a/Examples/test-suite/ruby/swig_assert.rb +++ b/Examples/test-suite/ruby/swig_assert.rb @@ -1,12 +1,7 @@ #!/usr/bin/env ruby # -# A simple function to create useful asserts +# Useful assert functions # -# -# -# -# - # # Exception raised when some swig binding test fails @@ -15,6 +10,21 @@ class SwigRubyError < RuntimeError end +# +# Simple assertions. Strings are not needed as arguments. +# +def swig_assert_equal_simple(a, b) + unless a == b + raise SwigRubyError.new("\n#{a} expected but was \n#{b}") + end +end + +def swig_assert_simple(a) + unless a + raise SwigRubyError.new("assertion failed.") + end +end + # # Asserts whether a and b are equal. # diff --git a/Examples/test-suite/ruby_alias_global_function.i b/Examples/test-suite/ruby_alias_global_function.i new file mode 100644 index 000000000..bddb24959 --- /dev/null +++ b/Examples/test-suite/ruby_alias_global_function.i @@ -0,0 +1,11 @@ +%module ruby_alias_global_function + +%alias get_my_name "nickname,fullname"; + +%inline %{ + +const char *get_my_name(){ + return "Chester Tester"; +} + +%} diff --git a/Examples/test-suite/ruby_alias_method.i b/Examples/test-suite/ruby_alias_method.i new file mode 100644 index 000000000..9ddcfce5e --- /dev/null +++ b/Examples/test-suite/ruby_alias_method.i @@ -0,0 +1,26 @@ +%module ruby_alias_method +%include + +%alias Synonym::getMyName "nickname,fullname" + +%inline %{ + +class Synonym { +private: + std::string myName; + +public: + Synonym(std::string myName); + + std::string getMyName(); +}; + +Synonym::Synonym(std::string myName){ + this->myName = myName; +}; + +std::string Synonym::getMyName(){ + return this->myName; +}; + +%} diff --git a/Examples/test-suite/ruby_alias_module_function.i b/Examples/test-suite/ruby_alias_module_function.i new file mode 100644 index 000000000..900de5f1d --- /dev/null +++ b/Examples/test-suite/ruby_alias_module_function.i @@ -0,0 +1,11 @@ +%module ruby_alias_module_function + +%alias get_my_name "nickname,fullname"; + +%inline %{ + +const char *get_my_name(){ + return "Chester Tester"; +} + +%} diff --git a/Examples/test-suite/ruby_rdata.i b/Examples/test-suite/ruby_rdata.i new file mode 100644 index 000000000..06af06f36 --- /dev/null +++ b/Examples/test-suite/ruby_rdata.i @@ -0,0 +1,20 @@ +%module ruby_rdata + +%{ + + class C {}; + + int take_proc_or_cpp_obj_and_ret_1(VALUE obj) { + return 1; + } + + int take_proc_or_cpp_obj_and_ret_1(C c) { + return 1; + } + +%} + +class C {}; + +int take_proc_or_cpp_obj_and_ret_1(VALUE); +int take_proc_or_cpp_obj_and_ret_1(C); diff --git a/Examples/test-suite/schemerunme/reference_global_vars.scm b/Examples/test-suite/schemerunme/reference_global_vars.scm index 4b3370cfc..29d0904b8 100644 --- a/Examples/test-suite/schemerunme/reference_global_vars.scm +++ b/Examples/test-suite/schemerunme/reference_global_vars.scm @@ -56,4 +56,12 @@ (if (!= (TestClass-num-get (value-TestClass (var-TestClass))) 20) (begin (display "Runtime test 13 failed.\n") (exit 1))) +; Test garbage collection on guile >= 2.0.12 +(if (or (and (string=? (major-version) "2") + (string=? (minor-version) "0") + (string>=? (micro-version) "12")) + (and (string>=? (major-version) "2") + (string>=? (minor-version) "1"))) + (gc)) + (exit 0) diff --git a/Examples/test-suite/scilab/Makefile.in b/Examples/test-suite/scilab/Makefile.in index 483ed2439..f873b8687 100644 --- a/Examples/test-suite/scilab/Makefile.in +++ b/Examples/test-suite/scilab/Makefile.in @@ -29,7 +29,7 @@ CPP_STD_TEST_CASES += \ include $(srcdir)/../common.mk -# Overriden variables +# Overridden variables SRCDIR = ../$(srcdir)/ # Local variables diff --git a/Examples/test-suite/scilab/li_std_container_typemaps_runme.sci b/Examples/test-suite/scilab/li_std_container_typemaps_runme.sci index e4832efe6..af87d54bf 100644 --- a/Examples/test-suite/scilab/li_std_container_typemaps_runme.sci +++ b/Examples/test-suite/scilab/li_std_container_typemaps_runme.sci @@ -6,7 +6,7 @@ function checkerror(ierr, cmd) if ierr <> 0 then swigtesterror("error " + string(ierr) + " in """ + cmd + """"); end endfunction -// test container of pointers returned from fonction (expected a list) +// test container of pointers returned from function (expected a list) function [classAPtr_list, classAPtr1, classAPtr2] = testCreateContainerPtr(container, value1, value2) classAPtr1 = new_ClassA(value1); classAPtr2 = new_ClassA(value2); @@ -57,7 +57,7 @@ endfunction // computed on the container function testContainerType(container, value_type, value1, value2, .. expected_returned_container, expected_accumulate_value) - // test container of basic type returned from fonction + // test container of basic type returned from function func = msprintf("ret_%s_%s", value_type, container); if value_type == "string" then cmd = msprintf("c = %s(''%s'', ''%s'');", func, value1, value2); diff --git a/Examples/test-suite/scilab/li_std_deque_runme.sci b/Examples/test-suite/scilab/li_std_deque_runme.sci index c0680846b..0903db4ae 100644 --- a/Examples/test-suite/scilab/li_std_deque_runme.sci +++ b/Examples/test-suite/scilab/li_std_deque_runme.sci @@ -25,7 +25,7 @@ IntDeque_push_back(intDeque, 6); avg = average(intDeque); checkequal(avg, 4.0, "average(intDeque)"); -// half shoud return a deque with elements half of the input elements +// half should return a deque with elements half of the input elements RealDeque_clear(realDeque); RealDeque_push_front(realDeque, 2.0); RealDeque_push_front(realDeque, 4.0); diff --git a/Examples/test-suite/scilab/null_pointer_runme.sci b/Examples/test-suite/scilab/null_pointer_runme.sci index 2c693d259..dab59acf8 100644 --- a/Examples/test-suite/scilab/null_pointer_runme.sci +++ b/Examples/test-suite/scilab/null_pointer_runme.sci @@ -2,6 +2,6 @@ exec("swigtest.start", -1); p = getnull(); checkequal(SWIG_this(p), 0, "SWIG_this(p)"); -checkequal(func(p), %T, "func(p)"); +checkequal(funk(p), %T, "funk(p)"); exec("swigtest.quit", -1); diff --git a/Examples/test-suite/scilab/overload_null_runme.sci b/Examples/test-suite/scilab/overload_null_runme.sci new file mode 100644 index 000000000..e3939ac5c --- /dev/null +++ b/Examples/test-suite/scilab/overload_null_runme.sci @@ -0,0 +1,45 @@ +exec("swigtest.start", -1); + +NULL = SWIG_ptr(0); + +o = new_Overload(); +x = new_X(); + +checkequal(1, Overload_byval1(o, x), "test 1"); +checkequal(2, Overload_byval1(o, NULL), "test 2"); + +checkequal(3, Overload_byval2(o, NULL), "test 3"); +checkequal(4, Overload_byval2(o, x), "test 4"); + +checkequal(5, Overload_byref1(o, x), "test 5"); +checkequal(6, Overload_byref1(o, NULL), "test 6"); + +checkequal(7, Overload_byref2(o, NULL), "test 7"); +checkequal(8, Overload_byref2(o, x), "test 8"); + +checkequal(9, Overload_byconstref1(o, x), "test 9"); +checkequal(10, Overload_byconstref1(o, NULL), "test 10"); + +checkequal(11, Overload_byconstref2(o, NULL), "test 11"); +checkequal(12, Overload_byconstref2(o, x), "test 12"); + +// const pointer references +checkequal(13, Overload_byval1cpr(o, x), "test 13"); +checkequal(14, Overload_byval1cpr(o, NULL), "test 14"); + +checkequal(15, Overload_byval2cpr(o, NULL), "test 15"); +checkequal(16, Overload_byval2cpr(o, x), "test 16"); + +// forward class declaration +checkequal(17, Overload_byval1forwardptr(o, x), "test 17"); +checkequal(18, Overload_byval1forwardptr(o, NULL), "test 18"); + +checkequal(19, Overload_byval2forwardptr(o, NULL), "test 19"); +checkequal(20, Overload_byval2forwardptr(o, x), "test 20"); + +checkequal(21, Overload_byval1forwardref(o, x), "test 21"); + +checkequal(22, Overload_byval2forwardref(o, x), "test 22"); + +exec("swigtest.quit", -1); + diff --git a/Examples/test-suite/scilab/scilab_li_matrix_runme.sci b/Examples/test-suite/scilab/scilab_li_matrix_runme.sci index 41924d6f9..55184cc20 100644 --- a/Examples/test-suite/scilab/scilab_li_matrix_runme.sci +++ b/Examples/test-suite/scilab/scilab_li_matrix_runme.sci @@ -2,7 +2,7 @@ exec("swigtest.start", -1); -// test matrix passed as output argument from fonction +// test matrix passed as output argument from function function test_outMatrix(func, valueType, expectedOutMatrix) funcName = msprintf("out%s%s", valueType, func); cmd = msprintf("outMatrix = %s();", funcName); @@ -13,7 +13,7 @@ function test_outMatrix(func, valueType, expectedOutMatrix) checkequal(outMatrix, expectedOutMatrix, funcName); endfunction -// test matrix passed as input argument of fonction +// test matrix passed as input argument of function function test_inMatrix(func, valueType, inMatrix, expectedInValue) funcName = msprintf("in%s%s", valueType, func); cmd = msprintf("inValue = %s(inMatrix);", funcName); @@ -24,7 +24,7 @@ function test_inMatrix(func, valueType, inMatrix, expectedInValue) checkequal(inValue, expectedInValue, funcName); endfunction -// test matrixes passed as input and output arguments of fonction +// test matrixes passed as input and output arguments of function function test_inoutMatrix(func, valueType, inoutMatrix, expectedInoutMatrix) funcName = msprintf("inout%s%s", valueType, func); cmd = msprintf("inoutMatrix = %s(inoutMatrix);", funcName); diff --git a/Examples/test-suite/scilab/scilab_pointer_conversion_functions_runme.sci b/Examples/test-suite/scilab/scilab_pointer_conversion_functions_runme.sci index d24f60eb9..1789c6111 100644 --- a/Examples/test-suite/scilab/scilab_pointer_conversion_functions_runme.sci +++ b/Examples/test-suite/scilab/scilab_pointer_conversion_functions_runme.sci @@ -15,4 +15,10 @@ checkequal(foo_addr, expected_foo_addr, "SWIG_this(pfoo_get())"); pfoo = SWIG_ptr(foo_addr); checkequal(equalFooPointer(pfoo), %T, "equalFooPointer(pfoo)"); +// Test conversion of mlist type pointers +stA = new_structA(); +checkequal(typeof(stA), "_p_structA"); +p = SWIG_ptr(stA); +checkequal(typeof(p), "pointer"); + exec("swigtest.quit", -1); diff --git a/Examples/test-suite/scilab/throw_exception_runme.sci b/Examples/test-suite/scilab/throw_exception_runme.sci index 2eada4be2..535a2f4b9 100644 --- a/Examples/test-suite/scilab/throw_exception_runme.sci +++ b/Examples/test-suite/scilab/throw_exception_runme.sci @@ -8,15 +8,15 @@ endfunction foo = new_Foo(); -checkException('Foo_test_int(foo)', 'Exception (int) occured: 37'); +checkException('Foo_test_int(foo)', 'Exception (int) occurred: 37'); -checkException('Foo_test_msg(foo)', 'Exception (char const *) occured: Dead'); +checkException('Foo_test_msg(foo)', 'Exception (char const *) occurred: Dead'); -checkException('Foo_test_multi(foo, 1)', 'Exception (int) occured: 37'); +checkException('Foo_test_multi(foo, 1)', 'Exception (int) occurred: 37'); -checkException('Foo_test_multi(foo, 2)', 'Exception (char const *) occured: Dead'); +checkException('Foo_test_multi(foo, 2)', 'Exception (char const *) occurred: Dead'); -checkException('Foo_test_cls(foo)', 'Exception (CError) occured.'); +checkException('Foo_test_cls(foo)', 'Exception (CError) occurred.'); delete_Foo(foo); diff --git a/Examples/test-suite/scilab/varargs_overload_runme.sci b/Examples/test-suite/scilab/varargs_overload_runme.sci index 7603b667c..7426e8165 100644 --- a/Examples/test-suite/scilab/varargs_overload_runme.sci +++ b/Examples/test-suite/scilab/varargs_overload_runme.sci @@ -4,7 +4,7 @@ checkequal(vararg_over1("Hello"), "Hello", "vararg_over1(""Hello"")"); checkequal(vararg_over1(2), "2", "vararg_over1(2)"); -checkequal(vararg_over2("Hello"), "Hello", "vararg_over1(""Hello"")"); +checkequal(vararg_over2("Hello"), "Hello", "vararg_over2(""Hello"")"); checkequal(vararg_over2(2, 2.2), "2 2.2", "vararg_over2(2, 2.2)") @@ -18,4 +18,24 @@ checkequal(vararg_over4(123), "123", "vararg_over4(123)"); checkequal(vararg_over4("Hello", 123), "Hello", "vararg_over4(""Hello"", 123)"); + +// Same as above but non-vararg function declared first + +checkequal(vararg_over6("Hello"), "Hello", "vararg_over6(""Hello"")"); + +checkequal(vararg_over6(2), "2", "vararg_over6(2)"); + +checkequal(vararg_over7("Hello"), "Hello", "vararg_over7(""Hello"")"); + +checkequal(vararg_over7(2, 2.2), "2 2.2", "vararg_over7(2, 2.2)") + +checkequal(vararg_over8("Hello"), "Hello", "vararg_over8(""Hello"")"); + +checkequal(vararg_over8(2, 2.2, "hey"), "2 2.2 hey", "vararg_over8(2, 2.2, ""hey"")"); + +checkequal(vararg_over9("Hello"), "Hello", "vararg_over9(""Hello"")"); + +checkequal(vararg_over9(123), "123", "vararg_over9(123)"); + +checkequal(vararg_over9("Hello", 123), "Hello", "vararg_over9(""Hello"", 123)"); exec("swigtest.quit", -1); diff --git a/Examples/test-suite/scilab_pointer_conversion_functions.i b/Examples/test-suite/scilab_pointer_conversion_functions.i index 5e29926c1..339627c1a 100644 --- a/Examples/test-suite/scilab_pointer_conversion_functions.i +++ b/Examples/test-suite/scilab_pointer_conversion_functions.i @@ -4,7 +4,7 @@ %inline %{ -void* getNull() { return NULL; } +void *getNull() { return NULL; } bool isNull(void *p) { return p == NULL; } int foo = 3; @@ -15,4 +15,17 @@ bool equalFooPointer(void *p) { return p == pfoo; } %} +%typemap(out, noblock=1) struct structA* { + if (SwigScilabPtrFromObject(pvApiCtx, SWIG_Scilab_GetOutputPosition(), $1, SWIG_Scilab_TypeQuery("struct structA *"), 0, NULL) != SWIG_OK) { + return SWIG_ERROR; + } + SWIG_Scilab_SetOutput(pvApiCtx, SWIG_NbInputArgument(pvApiCtx) + SWIG_Scilab_GetOutputPosition()); +} +%inline %{ + +struct structA { + int x; +}; + +%} diff --git a/Examples/test-suite/simutry.i b/Examples/test-suite/simutry.i index addea14db..ad45da425 100644 --- a/Examples/test-suite/simutry.i +++ b/Examples/test-suite/simutry.i @@ -23,7 +23,7 @@ namespace simuPOP { } - virtual int func() const + virtual int funk() const { return m_pop.m_a; } }; @@ -32,7 +32,7 @@ namespace simuPOP struct DerivedOperator: public Operator { DerivedOperator(int a):Operator(a){} - virtual int func() const + virtual int funk() const { return 2*this->m_pop.m_a; } }; @@ -90,7 +90,7 @@ namespace simuPOP void test( const std::vector< Operator*>& para) { for( size_t i =0; i < para.size(); ++i) - para[i]->func(); + para[i]->funk(); } } } diff --git a/Examples/test-suite/smart_pointer_ignore.i b/Examples/test-suite/smart_pointer_ignore.i index f369de782..146a5e49e 100644 --- a/Examples/test-suite/smart_pointer_ignore.i +++ b/Examples/test-suite/smart_pointer_ignore.i @@ -6,12 +6,12 @@ %inline %{ class Base { public: - void base() {} + void baseMethod() {} }; class Derived : public Base { public: - void derived() {} + void derivedMethod() {} }; template diff --git a/Examples/test-suite/smart_pointer_namespace2.i b/Examples/test-suite/smart_pointer_namespace2.i index 882799862..e78364c25 100644 --- a/Examples/test-suite/smart_pointer_namespace2.i +++ b/Examples/test-suite/smart_pointer_namespace2.i @@ -49,11 +49,6 @@ namespace one }; } -%define PTR_DEF(o) -typedef one::Ptr o ## _ptr; -%template(o ## _ptr) one::Ptr; -%enddef - namespace one { class Obj1 @@ -63,7 +58,8 @@ namespace one void donothing() {} }; - PTR_DEF(Obj1) + typedef one::Ptr Obj1_ptr; + %template(Obj1_ptr) one::Ptr; } namespace two @@ -75,6 +71,9 @@ namespace two void donothing() {} }; - PTR_DEF(Obj2) + typedef one::Ptr Obj2_ptr; } +using two::Obj2; +%template(Obj2_ptr) one::Ptr; + diff --git a/Examples/test-suite/smart_pointer_overload.i b/Examples/test-suite/smart_pointer_overload.i index 0d2cc595d..08248d295 100644 --- a/Examples/test-suite/smart_pointer_overload.i +++ b/Examples/test-suite/smart_pointer_overload.i @@ -4,8 +4,6 @@ %warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) test; #endif -#ifndef SWIG_NO_OVERLOAD - %inline %{ struct Foo { int x; @@ -24,5 +22,3 @@ public: }; %} -#endif - diff --git a/Examples/test-suite/static_const_member_2.i b/Examples/test-suite/static_const_member_2.i index 0b6d38d21..0b38b394b 100644 --- a/Examples/test-suite/static_const_member_2.i +++ b/Examples/test-suite/static_const_member_2.i @@ -4,6 +4,10 @@ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) oss::modules::CavityPackFlags::backward_field; %warnfilter(SWIGWARN_RUBY_WRONG_NAME) oss::modules::Test::current_profile; +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %inline %{ namespace oss { diff --git a/Examples/test-suite/std_containers.i b/Examples/test-suite/std_containers.i index ae69b6418..80409a1f0 100644 --- a/Examples/test-suite/std_containers.i +++ b/Examples/test-suite/std_containers.i @@ -115,6 +115,10 @@ return v; } + std::vector videntb(const std::vector& v) + { + return v; + } int get_elem(const std::vector& v, int index) { diff --git a/Examples/test-suite/stl_no_default_constructor.i b/Examples/test-suite/stl_no_default_constructor.i new file mode 100644 index 000000000..32aff2b46 --- /dev/null +++ b/Examples/test-suite/stl_no_default_constructor.i @@ -0,0 +1,19 @@ +%module stl_no_default_constructor + +%include + +%inline %{ +struct NoDefaultCtor { + int value; + NoDefaultCtor(int i) : value(i) {} +}; +%} + +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGD) +%template(VectorNoDefaultCtor) std::vector; +#endif + +#if defined(SWIGJAVA) || defined(SWIGJAVA) +%include +%template(ListNoDefaultCtor) std::list; +#endif diff --git a/Examples/test-suite/string_simple.i b/Examples/test-suite/string_simple.i index c319aa1ef..537daa570 100644 --- a/Examples/test-suite/string_simple.i +++ b/Examples/test-suite/string_simple.i @@ -1,10 +1,10 @@ %module string_simple -%newobject copy_string; +%newobject copy_str; %inline %{ #include -const char* copy_string(const char* str) { +const char* copy_str(const char* str) { size_t len = strlen(str); char* newstring = (char*) malloc(len + 1); strcpy(newstring, str); diff --git a/Examples/test-suite/swig_exception.i b/Examples/test-suite/swig_exception.i new file mode 100644 index 000000000..3cf8b406c --- /dev/null +++ b/Examples/test-suite/swig_exception.i @@ -0,0 +1,91 @@ +/* File : swig_exception.i + * Test SWIG_exception(). + */ +%module swig_exception + +%include exception.i + +%exception { + try { + $action + } catch (std::exception& e) { + SWIG_exception(SWIG_SystemError, e.what()); + } +} + +%inline %{ +class Value { + int a_; + int b_; +public: + Value(int a, int b) : a_(a), b_(b) {} +}; + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + } + double x, y; + void move(double dx, double dy); + virtual double area() = 0; + virtual double perimeter() = 0; + virtual Value throwException(); + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { } + virtual double area(); + virtual double perimeter(); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { } + virtual double area(); + virtual double perimeter(); +}; +%} + +%{ +#define PI 3.14159265358979323846 + +#include + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +Value Shape::throwException() { + throw std::logic_error("OK"); +} + +int Shape::nshapes = 0; + +double Circle::area() { + return PI*radius*radius; +} + +double Circle::perimeter() { + return 2*PI*radius; +} + +double Square::area() { + return width*width; +} + +double Square::perimeter() { + return 4*width; +} +%} diff --git a/Examples/test-suite/tcl/null_pointer_runme.tcl b/Examples/test-suite/tcl/null_pointer_runme.tcl index be99c7166..7ed87c153 100644 --- a/Examples/test-suite/tcl/null_pointer_runme.tcl +++ b/Examples/test-suite/tcl/null_pointer_runme.tcl @@ -3,7 +3,7 @@ if [ catch { load ./null_pointer[info sharedlibextension] null_pointer} err_msg } set a [A] -if {[func $a] != 0} { +if {[funk $a] != 0} { puts stderr "null_pointer test 1 failed" exit 1 } diff --git a/Examples/test-suite/tcl/overload_null_runme.tcl b/Examples/test-suite/tcl/overload_null_runme.tcl new file mode 100644 index 000000000..3716612ab --- /dev/null +++ b/Examples/test-suite/tcl/overload_null_runme.tcl @@ -0,0 +1,52 @@ + +if [ catch { load ./overload_null[info sharedlibextension] overload_null} err_msg ] { + puts stderr "Could not load shared object:\n$err_msg" +} + +proc check {what expected actual} { + if {$expected != $actual } { + error "Failed: $what Expected: $expected , Actual: $actual" + } +} + +set o [Overload] +set x [X] + +check "test1 " 1 [$o byval1 $x] +check "test2 " 2 [$o byval1 "NULL"] + +check "testX" 1 [$o byval1 $x] +check "testX" 2 [$o byval1 "NULL"] + +check "testX" 3 [$o byval2 "NULL"] +check "testX" 4 [$o byval2 $x] + +check "testX" 5 [$o byref1 $x] +check "testX" 6 [$o byref1 "NULL"] + +check "testX" 7 [$o byref2 "NULL"] +check "testX" 8 [$o byref2 $x] + +check "testX" 9 [$o byconstref1 $x] +check "testX" 10 [$o byconstref1 "NULL"] + +check "testX" 11 [$o byconstref2 "NULL"] +check "testX" 12 [$o byconstref2 $x] + +# const pointer references +check "testX" 13 [$o byval1cpr $x] +check "testX" 14 [$o byval1cpr "NULL"] + +check "testX" 15 [$o byval2cpr "NULL"] +check "testX" 16 [$o byval2cpr $x] + +# forward class declaration +check "testX" 17 [$o byval1forwardptr $x] +check "testX" 18 [$o byval1forwardptr "NULL"] + +check "testX" 19 [$o byval2forwardptr "NULL"] +check "testX" 20 [$o byval2forwardptr $x] + +check "testX" 21 [$o byval1forwardref $x] + +check "testX" 22 [$o byval2forwardref $x] diff --git a/Examples/test-suite/template_class_reuse_name.i b/Examples/test-suite/template_class_reuse_name.i new file mode 100644 index 000000000..818816d0e --- /dev/null +++ b/Examples/test-suite/template_class_reuse_name.i @@ -0,0 +1,132 @@ +%module template_class_reuse_name + +// One parameter templates +%inline %{ +namespace Space { + template struct Bool1 { void tt(){}; void ff(){}; }; + template struct Bool2 { void tt(){}; void ff(){}; }; + template struct Bool3 {}; + template <> struct Bool3 { void tt(){}; }; + template <> struct Bool3 { void ff(){}; }; + template struct Bool4 { void tt(){}; }; + template <> struct Bool4 { void ff(){}; }; +} +%} + +// Instantiated names are the same as C++ template name +%template(Bool1) Space::Bool1; +%template(Bool2) Space::Bool2; +%template(Bool3) Space::Bool3; +%template(Bool4) Space::Bool4; + +// Instantiated names are not the same as C++ template name +%template(Bool1False) Space::Bool1; +%template(Bool2False) Space::Bool2; +%template(Bool3False) Space::Bool3; +%template(Bool4False) Space::Bool4; + + +// Forward declared templates +%inline %{ +namespace Space { + template struct BoolForward1; + template struct BoolForward2; + template struct BoolForward3; + template struct BoolForward4; + + template struct BoolForward1 { void tt(){}; void ff(){}; }; + template struct BoolForward2 { void tt(){}; void ff(){}; }; + template struct BoolForward3 {}; + template <> struct BoolForward3 { void tt(){}; }; + template <> struct BoolForward3 { void ff(){}; }; + template struct BoolForward4 { void tt(){}; }; + template <> struct BoolForward4 { void ff(){}; }; +} +%} + +// Instantiated names are the same as C++ template name +%template(BoolForward1) Space::BoolForward1; +%template(BoolForward2) Space::BoolForward2; +%template(BoolForward3) Space::BoolForward3; +%template(BoolForward4) Space::BoolForward4; + +// Instantiated names are not the same as C++ template name +%template(BoolForward1False) Space::BoolForward1; +%template(BoolForward2False) Space::BoolForward2; +%template(BoolForward3False) Space::BoolForward3; +%template(BoolForward4False) Space::BoolForward4; + + +// Two parameter templates +%inline %{ +namespace Space { + template struct IntBool1 { void tt(){}; void ff(){}; }; + template struct IntBool2 { void tt(){}; void ff(){}; }; + template struct IntBool3 {}; + template struct IntBool3 { void tt(){}; }; + template struct IntBool3 { void ff(){}; }; + template struct IntBool4 { void tt(){}; }; + template struct IntBool4 { void ff(){}; }; +} +%} + +// Instantiated names are the same as C++ template name +%template(IntBool1) Space::IntBool1<0, true>; +%template(IntBool2) Space::IntBool2<0, true>; +%template(IntBool3) Space::IntBool3<0, true>; +%template(IntBool4) Space::IntBool4<0, true>; + +// Instantiated names are not the same as C++ template name +%template(IntBool1False) Space::IntBool1<0, false>; +%template(IntBool2False) Space::IntBool2<0, false>; +%template(IntBool3False) Space::IntBool3<0, false>; +%template(IntBool4False) Space::IntBool4<0, false>; + + +%{ +namespace Space { + template struct Duplicate1 { void ff(){}; }; +} +%} + +%warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate1; +namespace Space { + template struct Duplicate1 { void ff(){}; }; + template struct Duplicate1 { void ff(){}; }; +} + + +%warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate2; +%inline %{ +namespace Space { + template struct Duplicate2 { void n(){}; }; +} +%} +%template(Duplicate2_0) Space::Duplicate2<0>; +%template(Duplicate2_0) Space::Duplicate2<0>; + + +%warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate3; +%inline %{ +namespace Space { + template struct Duplicate3 { void n(){}; }; +} +%} +%template(Duplicate3) Space::Duplicate3<0>; +%template(Duplicate3) Space::Duplicate3<0>; + + +%{ +namespace Space { + template struct Duplicate4 { void ff(){}; }; +} +%} + +%warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate4; +namespace Space { + template struct Duplicate4 { void ff(){}; }; + template struct Duplicate4 { void ff(){}; }; +} +%template(Duplicate4) Space::Duplicate4<0>; +%template(Duplicate4) Space::Duplicate4<0>; + diff --git a/Examples/test-suite/template_default_cache.i b/Examples/test-suite/template_default_cache.i new file mode 100644 index 000000000..70bccd595 --- /dev/null +++ b/Examples/test-suite/template_default_cache.i @@ -0,0 +1,35 @@ +%module template_default_cache; + +%inline %{ + namespace d { + template< typename T > class d {}; + } +%} + +%ignore ns_a::iface1::Model; + +%inline %{ +namespace ns_a { + namespace iface1 { + class Model {}; + typedef d::d ModelPtr; + } + using iface1::ModelPtr; +} +%} + +%inline %{ +namespace ns_b { + namespace iface1 { + class Model { + public: + ns_a::ModelPtr foo() { return ns_a::ModelPtr(); }; + }; + typedef d::d ModelPtr; + ns_a::ModelPtr get_mp_a() { return ns_a::ModelPtr(); } + ModelPtr get_mp_b() { return ModelPtr(); } + } + } +%} +%template(AModelPtr) d::d; +%template(BModelPtr) d::d; diff --git a/Examples/test-suite/template_default_class_parms.i b/Examples/test-suite/template_default_class_parms.i index d07a1309f..02e993f32 100644 --- a/Examples/test-suite/template_default_class_parms.i +++ b/Examples/test-suite/template_default_class_parms.i @@ -1,5 +1,9 @@ %module template_default_class_parms +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %inline %{ namespace Space { struct SomeType {}; diff --git a/Examples/test-suite/template_default_class_parms_typedef.i b/Examples/test-suite/template_default_class_parms_typedef.i index 0767498bf..748b23cbb 100644 --- a/Examples/test-suite/template_default_class_parms_typedef.i +++ b/Examples/test-suite/template_default_class_parms_typedef.i @@ -4,6 +4,10 @@ %feature("python:nondynamic"); +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %inline %{ namespace Space { struct SomeType {}; diff --git a/Examples/test-suite/template_empty_inherit.i b/Examples/test-suite/template_empty_inherit.i new file mode 100644 index 000000000..5677b8b1a --- /dev/null +++ b/Examples/test-suite/template_empty_inherit.i @@ -0,0 +1,34 @@ +%module template_empty_inherit + +%rename(FunctorOperator) operator(); + +%inline %{ +template struct Functor { + virtual Result operator()(Arg x) const = 0; + virtual ~Functor() {} +}; +%} + +// Bug fix - %ignore was resulting in this warning: +// Warning 401: Base class 'Functor< int,int >' has no name as it is an empty template instantiated with '%template()'. Ignored. +%ignore Functor; +%template() Functor; + +%inline %{ +#include +#include +struct SquareFunctor : Functor { + int operator()(int v) const { return v*v; } +}; +%} + +%include +%template(VectorInt) std::vector; + +%inline %{ +std::vector squares(const std::vector& vi) { + std::vector result; + std::transform(vi.begin(), vi.end(), std::back_inserter(result), SquareFunctor()); + return result; +} +%} diff --git a/Examples/test-suite/template_nested_typemaps.i b/Examples/test-suite/template_nested_typemaps.i index 54f5bc503..577a88e14 100644 --- a/Examples/test-suite/template_nested_typemaps.i +++ b/Examples/test-suite/template_nested_typemaps.i @@ -1,25 +1,30 @@ -#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_TEMPLATE - %module template_nested_typemaps -// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods +#pragma SWIG nowarn=SWIGWARN_PARSE_NAMED_NESTED_CLASS -template struct Typemap { - %typemap(in) T { - $1 = -99; - } -}; -template <> struct Typemap { // Note explicit specialization - %typemap(in) short { - $1 = -77; - } -}; +// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods +// Only for languages that support nested classes %inline %{ int globalInt1(int s) { return s; } short globalShort1(short s) { return s; } template struct Breeze { + template struct Typemap { +#ifdef SWIG + %typemap(in) TMT { + $1 = -99; + } +#endif + }; + template struct TypemapShort { +#ifdef SWIG + %typemap(in) short { + $1 = -77; + } +#endif + }; + int methodInt1(int s) { return s; } #if defined(SWIG) %template() Typemap; @@ -29,7 +34,7 @@ template struct Breeze { short methodShort1(short s) { return s; } #if defined(SWIG) - %template(TypemapShort) Typemap; // should issue warning SWIGWARN_PARSE_NESTED_TEMPLATE + %template() TypemapShort; #endif short methodShort2(short s) { return s; } // should pick up the typemap within Typemap }; diff --git a/Examples/test-suite/template_opaque.i b/Examples/test-suite/template_opaque.i index b910e47e3..7aafd62e8 100644 --- a/Examples/test-suite/template_opaque.i +++ b/Examples/test-suite/template_opaque.i @@ -36,7 +36,4 @@ namespace A { } } -#ifndef SWIGCSHARP -// C# vector typemaps only ready for simple cases right now %template(OpaqueVectorType) std::vector; -#endif diff --git a/Examples/test-suite/template_parameters_global_scope.i b/Examples/test-suite/template_parameters_global_scope.i new file mode 100644 index 000000000..a828187b5 --- /dev/null +++ b/Examples/test-suite/template_parameters_global_scope.i @@ -0,0 +1,133 @@ +%module template_parameters_global_scope + +%inline %{ +namespace Alloc { + template struct Rebind { + typedef int Integer; + }; +} +%} + +%inline %{ +struct Bucket_ {}; +typedef Bucket_ TDBucket; +typedef ::Bucket_ TDGlobalBucket; +%} + +// Check 1: %template no unary scope operator +%template(RebindBucket) Alloc::Rebind< Bucket_ >; + +%inline %{ +Alloc::Rebind< Bucket_ >::Integer Bucket1() { return 1; } +Alloc::Rebind< ::Bucket_ >::Integer Bucket2() { return 2; } +Alloc::Rebind< TDBucket >::Integer Bucket3() { return 3; } +Alloc::Rebind< ::TDBucket >::Integer Bucket4() { return 4; } +Alloc::Rebind< TDGlobalBucket >::Integer Bucket5() { return 5; } +Alloc::Rebind< ::TDGlobalBucket >::Integer Bucket6() { return 6; } +%} + +// Check 2: %template with unary scope operator +%inline %{ +struct Spade {}; +typedef Spade TDSpade; +typedef ::Spade TDGlobalSpade; +%} +%template(RebindSpade) Alloc::Rebind< ::Spade >; + +%inline %{ +Alloc::Rebind< Spade >::Integer Spade1() { return 1; } +Alloc::Rebind< ::Spade >::Integer Spade2() { return 2; } +Alloc::Rebind< TDSpade >::Integer Spade3() { return 3; } +Alloc::Rebind< ::TDSpade >::Integer Spade4() { return 4; } +Alloc::Rebind< TDGlobalSpade >::Integer Spade5() { return 5; } +Alloc::Rebind< ::TDGlobalSpade >::Integer Spade6() { return 6; } +%} + +// Check 3: %template typedef no unary scope operator +%inline %{ +struct Ball {}; +typedef Ball TDBall; +typedef ::Ball TDGlobalBall; +%} +%template(RebindBall) Alloc::Rebind< TDBall >; + +%inline %{ +Alloc::Rebind< Ball >::Integer Ball1() { return 1; } +Alloc::Rebind< ::Ball >::Integer Ball2() { return 2; } +Alloc::Rebind< TDBall >::Integer Ball3() { return 3; } +Alloc::Rebind< ::TDBall >::Integer Ball4() { return 4; } +Alloc::Rebind< TDGlobalBall >::Integer Ball5() { return 5; } +Alloc::Rebind< ::TDGlobalBall >::Integer Ball6() { return 6; } +%} + +// Check 4: %template typedef with unary scope operator +%inline %{ +struct Bat {}; +typedef Bat TDBat; +typedef ::Bat TDGlobalBat; +%} +%template(RebindBat) Alloc::Rebind< ::TDBat >; + +%inline %{ +Alloc::Rebind< Bat >::Integer Bat1() { return 1; } +Alloc::Rebind< ::Bat >::Integer Bat2() { return 2; } +Alloc::Rebind< TDBat >::Integer Bat3() { return 3; } +Alloc::Rebind< ::TDBat >::Integer Bat4() { return 4; } +Alloc::Rebind< TDGlobalBat >::Integer Bat5() { return 5; } +Alloc::Rebind< ::TDGlobalBat >::Integer Bat6() { return 6; } +%} + +// Check 5: %template double typedef no unary scope operator +%inline %{ +struct Chair {}; +typedef Chair TDChair; +typedef ::Chair TDGlobalChair; +%} +%template(RebindChair) Alloc::Rebind< TDGlobalChair >; + +%inline %{ +Alloc::Rebind< Chair >::Integer Chair1() { return 1; } +Alloc::Rebind< ::Chair >::Integer Chair2() { return 2; } +Alloc::Rebind< TDChair >::Integer Chair3() { return 3; } +Alloc::Rebind< ::TDChair >::Integer Chair4() { return 4; } +Alloc::Rebind< TDGlobalChair >::Integer Chair5() { return 5; } +Alloc::Rebind< ::TDGlobalChair >::Integer Chair6() { return 6; } +%} + +// Check 6: %template double typedef with unary scope operator +%inline %{ +struct Table {}; +typedef Table TDTable; +typedef ::Table TDGlobalTable; +%} +%template(RebindTable) Alloc::Rebind< ::TDGlobalTable >; + +%inline %{ +Alloc::Rebind< Table >::Integer Table1() { return 1; } +Alloc::Rebind< ::Table >::Integer Table2() { return 2; } +Alloc::Rebind< TDTable >::Integer Table3() { return 3; } +Alloc::Rebind< ::TDTable >::Integer Table4() { return 4; } +Alloc::Rebind< TDGlobalTable >::Integer Table5() { return 5; } +Alloc::Rebind< ::TDGlobalTable >::Integer Table6() { return 6; } +%} + +#if 0 +%inline %{ +namespace Alloc { + template struct Rejig { + typedef int Integer; + }; +} +%} + +%template(RejigSpade) Alloc::Rejig<::Spade>; + +%inline %{ +Alloc::Rejig<>::Integer rejig1() { return 1; } +Alloc::Rejig< ::Spade >::Integer rejig2() { return 2; } +Alloc::Rejig< ::TDSpade >::Integer rejig3() { return 3; } +Alloc::Rejig< ::TDSpade >::Integer rejig4() { return 4; } +Alloc::Rejig< TDGlobalSpade >::Integer rejig5() { return 5; } +Alloc::Rejig< ::TDGlobalSpade >::Integer rejig6() { return 6; } +%} +#endif diff --git a/Examples/test-suite/template_partial_specialization.i b/Examples/test-suite/template_partial_specialization.i index 8781fbbda..9727b52f8 100644 --- a/Examples/test-suite/template_partial_specialization.i +++ b/Examples/test-suite/template_partial_specialization.i @@ -12,10 +12,10 @@ namespace One { template <> struct OneParm { void g() {} }; template <> struct OneParm { void h() {} }; - template <> struct OneParm { void i() {} }; - template <> struct OneParm { void j() {} }; - template <> struct OneParm { void k() {} }; - template <> struct OneParm { void l() {} }; + template <> struct OneParm { void j() {} }; + template <> struct OneParm { void k() {} }; + template <> struct OneParm { void m() {} }; + template <> struct OneParm { void n() {} }; } %} @@ -32,17 +32,17 @@ namespace One { %template(H) One::OneParm; // %template scope explicit specializations -namespace ONE { - %template(I) One::OneParm; - %template(J) ::One::OneParm; -} -%template(K) ::One::OneParm; namespace One { - %template(L) OneParm; + %template(J) One::OneParm; + %template(K) ::One::OneParm; +} +%template(M) ::One::OneParm; +namespace One { + %template(N) OneParm; } // %template scope partial specializations -namespace ONE { +namespace One { %template(BB) One::OneParm; %template(BBB) ::One::OneParm; } diff --git a/Examples/test-suite/template_partial_specialization_typedef.i b/Examples/test-suite/template_partial_specialization_typedef.i index 6fdbf99aa..6f8a11591 100644 --- a/Examples/test-suite/template_partial_specialization_typedef.i +++ b/Examples/test-suite/template_partial_specialization_typedef.i @@ -39,10 +39,10 @@ namespace One { template <> struct OneParm { void g() {} }; template <> struct OneParm { void h() {} }; - template <> struct OneParm { void i() {} }; - template <> struct OneParm { void j() {} }; - template <> struct OneParm { void k() {} }; - template <> struct OneParm { void l() {} }; + template <> struct OneParm { void j() {} }; + template <> struct OneParm { void k() {} }; + template <> struct OneParm { void m() {} }; + template <> struct OneParm { void n() {} }; } %} @@ -59,17 +59,17 @@ namespace One { %template(H) One::OneParm; // %template scope explicit specializations -namespace ONE { - %template(I) One::OneParm; - %template(J) ::One::OneParm; -} -%template(K) ::One::OneParm; namespace One { - %template(L) OneParm; + %template(J) One::OneParm; + %template(K) ::One::OneParm; +} +%template(M) ::One::OneParm; +namespace One { + %template(N) OneParm; } // %template scope partial specializations -namespace ONE { +namespace One { %template(BB) One::OneParm; %template(BBB) ::One::OneParm; } diff --git a/Examples/test-suite/template_typedef_class_template.i b/Examples/test-suite/template_typedef_class_template.i index fc8151ff0..e391c6a3a 100644 --- a/Examples/test-suite/template_typedef_class_template.i +++ b/Examples/test-suite/template_typedef_class_template.i @@ -1,5 +1,9 @@ %module template_typedef_class_template +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %inline %{ namespace Standard { template struct Pair { diff --git a/Examples/test-suite/template_typedef_cplx5.i b/Examples/test-suite/template_typedef_cplx5.i index 84b09fd78..566696992 100644 --- a/Examples/test-suite/template_typedef_cplx5.i +++ b/Examples/test-suite/template_typedef_cplx5.i @@ -7,7 +7,7 @@ %inline %{ - // This typedef triggers an inifinite recursion + // This typedef triggers an infinite recursion // in the next test1() nd test2() function declarations typedef std::complex complex; diff --git a/Examples/test-suite/template_typemaps.i b/Examples/test-suite/template_typemaps.i index d01945460..38a9c66de 100644 --- a/Examples/test-suite/template_typemaps.i +++ b/Examples/test-suite/template_typemaps.i @@ -25,6 +25,10 @@ %typemap(out) Integer2 { /* do nothing */ } #endif +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %{ typedef int Integer1; %} diff --git a/Examples/test-suite/template_typemaps_typedef.i b/Examples/test-suite/template_typemaps_typedef.i index 022fe884f..44c485dfb 100644 --- a/Examples/test-suite/template_typemaps_typedef.i +++ b/Examples/test-suite/template_typemaps_typedef.i @@ -2,6 +2,10 @@ // Similar to template_typedef_class_template // Testing typemaps of a typedef of a nested class in a template and where the template uses default parameters +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %inline %{ namespace Standard { template struct Pair { diff --git a/Examples/test-suite/template_typemaps_typedef2.i b/Examples/test-suite/template_typemaps_typedef2.i index 64055c4ea..443fa3627 100644 --- a/Examples/test-suite/template_typemaps_typedef2.i +++ b/Examples/test-suite/template_typemaps_typedef2.i @@ -4,6 +4,10 @@ // Similar to template_typedef_class_template // Testing typemaps of a typedef of a nested class in a template and where the template uses default parameters +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %inline %{ namespace Standard { template struct Pair { diff --git a/Examples/test-suite/template_using_directive_typedef.i b/Examples/test-suite/template_using_directive_typedef.i new file mode 100644 index 000000000..1c8bcb9dd --- /dev/null +++ b/Examples/test-suite/template_using_directive_typedef.i @@ -0,0 +1,44 @@ +%module template_using_directive_typedef + +%inline %{ +namespace space { + template class Vector {}; + class VectorClass {}; +} +struct Obj {}; +%} + +%template(Vector_Obj) space::Vector; + +%inline %{ +namespace tns { + using space::Vector; // template using directives were not being added into the typedef table + using space::VectorClass; + typedef Vector NSVec; +} +%} + +%inline %{ +namespace tns { + struct Holder { +// using Vec = Vector; + typedef Vector Vec; + typedef VectorClass VecClass; + Vec items; + void holder_use1(space::Vector, tns::NSVec, tns::Vector) {} + void holder_use2(space::Vector, NSVec, Vector) {} + void holder_use3(tns::Holder::Vec, Holder::Vec, Vec) {} + }; + void tns_holder_use(tns::Holder::Vec, Holder::Vec) {} + void tns_use(space::Vector, NSVec, tns::NSVec) {} +} +void global_holder_use(tns::Holder::Vec) {} +void global_use(space::Vector, tns::NSVec, tns::Vector) {} +namespace ns1 { + void ns1_holder_use(tns::Holder::Vec) {} +} +namespace ns2 { + using namespace tns; + void ns2_holder_use(tns::Holder::Vec, Holder::Vec, NSVec, Vector) {} +} +%} diff --git a/Examples/test-suite/template_virtual.i b/Examples/test-suite/template_virtual.i index 8c844f946..c760e1833 100644 --- a/Examples/test-suite/template_virtual.i +++ b/Examples/test-suite/template_virtual.i @@ -1,7 +1,7 @@ %module template_virtual // Submitted by Marcelo Matus -// assertion emmitted with templates + derivation + pure virtual member +// assertion emitted with templates + derivation + pure virtual member // allocate.cxx:47: int Allocate::is_abstract_inherit(Node*, Node*): // Assertion `dn' failed. diff --git a/Examples/test-suite/threads_exception.i b/Examples/test-suite/threads_exception.i index caa79c78e..4708633db 100644 --- a/Examples/test-suite/threads_exception.i +++ b/Examples/test-suite/threads_exception.i @@ -4,6 +4,14 @@ %module(threads="1") threads_exception +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) +#define TESTCASE_THROW3(T1, T2, T3) throw(T1, T2, T3) +%{ +#define TESTCASE_THROW1(T1) +#define TESTCASE_THROW3(T1, T2, T3) +%} + %{ struct A {}; %} @@ -11,10 +19,6 @@ struct A {}; %inline %{ #include -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif - class Exc { public: Exc(int c, const char *m) { @@ -28,24 +32,24 @@ public: class Test { public: - int simple() throw(int) { + int simple() TESTCASE_THROW1(int) { throw(37); return 1; } - int message() throw(const char *) { + int message() TESTCASE_THROW1(const char *) { throw("I died."); return 1; } - int hosed() throw(Exc) { + int hosed() TESTCASE_THROW1(Exc) { throw(Exc(42,"Hosed")); return 1; } - int unknown() throw(A*) { + int unknown() TESTCASE_THROW1(A*) { static A a; throw &a; return 1; } - int multi(int x) throw(int, const char *, Exc) { + int multi(int x) TESTCASE_THROW3(int, const char *, Exc) { if (x == 1) throw(37); if (x == 2) throw("Bleah!"); if (x == 3) throw(Exc(42,"No-go-diggy-die")); diff --git a/Examples/test-suite/throw_exception.i b/Examples/test-suite/throw_exception.i index 396c633a6..ed9288290 100644 --- a/Examples/test-suite/throw_exception.i +++ b/Examples/test-suite/throw_exception.i @@ -1,9 +1,11 @@ %module throw_exception +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW1(T1) throw(T1) +#define TESTCASE_THROW3(T1, T2, T3) throw(T1, T2, T3) %{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +#define TESTCASE_THROW1(T1) +#define TESTCASE_THROW3(T1, T2, T3) %} %warnfilter(SWIGWARN_RUBY_WRONG_NAME) Namespace::enum1; @@ -30,45 +32,45 @@ namespace Namespace { } class Foo { public: - void test_int() throw(int) { + void test_int() TESTCASE_THROW1(int) { throw 37; } - void test_msg() throw(const char *) { + void test_msg() TESTCASE_THROW1(const char *) { throw "Dead"; } - void test_cls() throw(CError) { + void test_cls() TESTCASE_THROW1(CError) { throw CError(); } - void test_cls_ptr() throw(CError *) { + void test_cls_ptr() TESTCASE_THROW1(CError *) { static CError StaticError; throw &StaticError; } - void test_cls_ref() throw(CError &) { + void test_cls_ref() TESTCASE_THROW1(CError &) { static CError StaticError; throw StaticError; } - void test_cls_td() throw(Namespace::ErrorTypedef) { + void test_cls_td() TESTCASE_THROW1(Namespace::ErrorTypedef) { throw CError(); } - void test_cls_ptr_td() throw(Namespace::ErrorPtr) { + void test_cls_ptr_td() TESTCASE_THROW1(Namespace::ErrorPtr) { static CError StaticError; throw &StaticError; } - void test_cls_ref_td() throw(Namespace::ErrorRef) { + void test_cls_ref_td() TESTCASE_THROW1(Namespace::ErrorRef) { static CError StaticError; throw StaticError; } - void test_array() throw(Namespace::IntArray) { + void test_array() TESTCASE_THROW1(Namespace::IntArray) { static Namespace::IntArray array; for (int i=0; i<10; i++) { array[i] = i; } throw array; } - void test_enum() throw(Namespace::EnumTest) { + void test_enum() TESTCASE_THROW1(Namespace::EnumTest) { throw Namespace::enum2; } - void test_multi(int x) throw(int, const char *, CError) { + void test_multi(int x) TESTCASE_THROW3(int, const char *, CError) { if (x == 1) throw 37; if (x == 2) throw "Dead"; if (x == 3) throw CError(); diff --git a/Examples/test-suite/typedef_classforward_same_name.i b/Examples/test-suite/typedef_classforward_same_name.i new file mode 100644 index 000000000..ad2e456f8 --- /dev/null +++ b/Examples/test-suite/typedef_classforward_same_name.i @@ -0,0 +1,15 @@ +%module typedef_classforward_same_name + +%inline %{ +typedef struct Foo Foo; +struct Foo { + int x; +}; +int extractFoo(Foo* foo) { return foo->x; } + +struct Boo { + int x; +}; +typedef struct Boo Boo; +int extractBoo(Boo* boo) { return boo->x; } +%} diff --git a/Examples/test-suite/typedef_funcptr.i b/Examples/test-suite/typedef_funcptr.i index f8cdd14b3..45ea99ef2 100644 --- a/Examples/test-suite/typedef_funcptr.i +++ b/Examples/test-suite/typedef_funcptr.i @@ -21,6 +21,16 @@ extern "C" Integer do_op(Integer x, Integer y, Integer (*op)(Integer, Integer)) { return (*op)(x,y); } + +typedef int (*FnPtr_int_td)(int, int); +int do_op_typedef_int(int x, int y, FnPtr_int_td op) { + return (*op)(x,y); +} + +typedef Integer (*FnPtr_Integer_td)(Integer, Integer); +Integer do_op_typedef_Integer(Integer x, Integer y, FnPtr_Integer_td op) { + return (*op)(x,y); +} %} %constant int addf(int x, int y); diff --git a/Examples/test-suite/typemap_delete.i b/Examples/test-suite/typemap_delete.i index eb6abe73c..fa62803cb 100644 --- a/Examples/test-suite/typemap_delete.i +++ b/Examples/test-suite/typemap_delete.i @@ -1,5 +1,9 @@ %module typemap_delete +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) val; +#endif + %typemap(in) Rect* (Rect temp) { $1 = 0; will_not_compile diff --git a/Examples/test-suite/typemap_documentation.i b/Examples/test-suite/typemap_documentation.i new file mode 100644 index 000000000..b7c1ddd22 --- /dev/null +++ b/Examples/test-suite/typemap_documentation.i @@ -0,0 +1,50 @@ +%module typemap_documentation + +// A place for checking that documented typemaps are working. +// The UTL languages are the only ones that are consistent enough to support these generic typemap functions. +// These are in the Typemaps.html chapter. + +%inline %{ +class Foo { +public: + int x; +}; + +class Bar { +public: + int y; +}; +%} + +#if defined(SWIGUTL) +%typemap(in) Foo * { + if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) { + SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo"); + } +} +#endif + +%inline %{ +int GrabVal(Foo *f) { + return f->x; +} +%} + + +#if defined(SWIGUTL) +%typemap(in) Foo * { + if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) { + Bar *temp; + if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &temp, $descriptor(Bar *), 0))) { + SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo or Bar"); + } + $1 = (Foo *)temp; + } +} +#endif + +%inline %{ +int GrabValFooBar(Foo *f) { + return f->x; +} +%} diff --git a/Examples/test-suite/typemap_template.i b/Examples/test-suite/typemap_template.i index 7ef77c79d..9f283105b 100644 --- a/Examples/test-suite/typemap_template.i +++ b/Examples/test-suite/typemap_template.i @@ -27,7 +27,7 @@ template struct TemplateTest1 { %template(TTint) TemplateTest1< int >; %inline %{ - void extratest(const TemplateTest1< YY > &t, + void extratest(const TemplateTest1< YY > &t, const TemplateTest1< ZZ > &tt, const TemplateTest1< int > &ttt) {} @@ -38,3 +38,27 @@ template struct TemplateTest1 { %inline %{ void wasbug(TemplateTest1< int >::Double wbug) {} %} + +/* Test bug where the %apply directive was ignored inside anonymous template + * instantiations */ + +template +struct Foo { + %typemap(in) Foo "" + %apply Foo { const Foo & } +}; + +%{ +template struct Foo {}; +%} + +%template(Foo_int) Foo; +%template() Foo; + +%inline %{ + void this_works(Foo f) {} + void this_also_works(const Foo& f) {} + void this_also_also_works(Foo f) {} + void this_used_to_fail(const Foo& f) {} +%} + diff --git a/Examples/test-suite/typemap_template_parms.i b/Examples/test-suite/typemap_template_parms.i new file mode 100644 index 000000000..fd0f7f51a --- /dev/null +++ b/Examples/test-suite/typemap_template_parms.i @@ -0,0 +1,28 @@ +%module typemap_template_parms + +%typemap(ret) int "_this_will_not_compile_int_$symname" + +%extend X { +%typemap(ret) T lake "/* ret lake X */" +%typemap(ret) T X::rake "/* ret rake X */" + +// Overrides below: %typemap(ret) T take +%typemap(ret) T X::take "/* ret take X */" +} + +%inline %{ +template struct X { +#if defined(SWIG) +%typemap(ret) T bake "/* ret bake X */" +%typemap(ret) T X::make "/* ret make X */" +%typemap(ret) T take "_rake_T_this_will_not_compile_" +#endif + T bake() { return T(); } + T make() { return T(); } + T lake() { return T(); } + T rake() { return T(); } + T take() { return T(); } +}; +%} + +%template(Xint) X; diff --git a/Examples/test-suite/typemap_template_typedef.i b/Examples/test-suite/typemap_template_typedef.i new file mode 100644 index 000000000..6605ec711 --- /dev/null +++ b/Examples/test-suite/typemap_template_typedef.i @@ -0,0 +1,66 @@ +%module typemap_template_typedef +//%module("templatereduce") typemap_template_typedef + +%typemap(in) int TMAP55 %{ $1 = 55; /* int TMAP55 typemap */ %} +%typemap(in) int TMAP66 %{ $1 = 66; /* int TMAP66 typemap */ %} +%typemap(in) int TMAP77 %{ $1 = 77; /* int TMAP77 typemap */ %} +%typemap(in) int TMAP88 %{ $1 = 88; /* int TMAP88 typemap */ %} + +%apply int TMAP77 { XXX::Long cc } + +%inline %{ +typedef int MyInteger; + +template struct XXX { +#ifdef SWIG +// In swig-3.0.12 'Long aa' was actually stored as 'long aa' in typemap table instead of 'XXX::Long aa' +%apply int TMAP55 { Long aa } +%apply int TMAP66 { XXX::Long bb } +%apply int TMAP88 { XXX::Long dd } +#endif + typedef long Long; + long aa1(long aa) { return aa; } + long aa2(Long aa) { return aa; } + long bb1(long bb) { return bb; } + long bb2(Long bb) { return bb; } + long cc1(long cc) { return cc; } + long cc2(Long cc) { return cc; } + long dd1(long dd) { return dd; } + long dd2(Long dd) { return dd; } +#ifdef SWIG +%clear Long aa; +%clear XXX::Long bb; +%clear XXX::Long dd; +#endif + long aa3(Long aa) { return aa; } + long bb3(Long bb) { return bb; } + long cc3(Long cc) { return cc; } + long dd3(Long dd) { return dd; } +}; +%} + +%template(XXXInt) XXX; + +%clear XXX::Long cc; + +%inline %{ + long aa1(XXX::Long aa) { return aa; } + long aa2(long aa) { return aa; } + long bb1(XXX::Long bb) { return bb; } + long bb2(long bb) { return bb; } + long cc1(XXX::Long cc) { return cc; } + long cc2(long cc) { return cc; } + long dd1(XXX::Long dd) { return dd; } + long dd2(long dd) { return dd; } +%} + +%inline %{ +typedef MyInteger MY_INTEGER; +template struct YYY { + void meff(T1 t1, T2 t2) {} +}; +%} +%template(YYYIntInt) YYY; +%inline %{ + void whyohwhy(YYY yy) {} +%} diff --git a/Examples/test-suite/typemap_various.i b/Examples/test-suite/typemap_various.i index c2f70ce55..3436bac1c 100644 --- a/Examples/test-suite/typemap_various.i +++ b/Examples/test-suite/typemap_various.i @@ -25,23 +25,33 @@ void foo1(Foo f, const Foo& ff) {} void foo2(Foo f, const Foo& ff) {} %} -#ifdef SWIGUTL -%typemap(ret) int Bar1::foo() { /* hello1 */ }; -%typemap(ret) int Bar2::foo() { /* hello2 */ }; -%typemap(ret) int foo() {/* hello3 */ }; -#endif +// Check "ret" typemap is implemented +%{ + template struct NeededForTest {}; +%} +%fragment("NeededForTest", "header") %{ + template<> struct NeededForTest { NeededForTest(short) {} }; +%} + +%typemap(ret) short "_ret_typemap_for_short_no_compile" +%typemap(ret, fragment="NeededForTest") short Bar1::foofunction() { /* ret typemap for short */ NeededForTest needed($1); }; +%typemap(ret, fragment="NeededForTest") short globalfoofunction() { /* ret typemap for short */ NeededForTest needed($1); }; %inline %{ struct Bar1 { - int foo() { return 1;} - }; - - struct Bar2 { - int foo() { return 1;} + short foofunction() { return 1;} }; + short globalfoofunction() { return 1;} %} - +%{ +void CheckRetTypemapUsed() { + // If the "ret" typemap is not used, the NeededForTest template specialization will not have been + // generated and so the following code will result in a compile failure + NeededForTest needed(111); + (void)needed; +} +%} %newobject FFoo::Bar(bool) const ; %typemap(newfree) char* Bar(bool) { @@ -62,7 +72,7 @@ void foo2(Foo f, const Foo& ff) {} #endif // Test obscure bug where named typemaps where not being applied when symbol name contained a number -%typemap(out) double "_typemap_for_double_no_compile_" +%typemap(out) double "_out_typemap_for_double_no_compile_" %typemap(out) double ABCD::meth {$1 = 0.0; TYPEMAP_OUT_INIT} %typemap(out) double ABCD::m1 {$1 = 0.0; TYPEMAP_OUT_INIT} %typemap(out) double ABCD::_x2 {$1 = 0.0; TYPEMAP_OUT_INIT} diff --git a/Examples/test-suite/unicode_strings.i b/Examples/test-suite/unicode_strings.i index 9be3748e6..e7266266e 100644 --- a/Examples/test-suite/unicode_strings.i +++ b/Examples/test-suite/unicode_strings.i @@ -20,4 +20,6 @@ char *charstring(char *s) { return s; } +void instring(const char *s) { +} %} diff --git a/Examples/test-suite/using_pointers.i b/Examples/test-suite/using_pointers.i index b2d6abe4d..1a3824afa 100644 --- a/Examples/test-suite/using_pointers.i +++ b/Examples/test-suite/using_pointers.i @@ -4,10 +4,10 @@ %csmethodmodifiers x "public new" #endif +// throw is invalid in C++17 and later, only SWIG to use it +#define TESTCASE_THROW2(T1, T2) throw(T1, T2) %{ -#if defined(_MSC_VER) - #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) -#endif +#define TESTCASE_THROW2(T1, T2) %} %inline %{ @@ -16,7 +16,7 @@ int x; virtual ~Foo() { } virtual Foo* blah() { return this; } - virtual Foo* exception_spec(int what_to_throw) throw (int, const char *) { + virtual Foo* exception_spec(int what_to_throw) TESTCASE_THROW2(int, const char *) { int num = 10; const char *str = "exception message"; if (what_to_throw == 1) throw num; diff --git a/Examples/test-suite/valuewrapper_opaque.i b/Examples/test-suite/valuewrapper_opaque.i index 52da89391..bc7ba8683 100644 --- a/Examples/test-suite/valuewrapper_opaque.i +++ b/Examples/test-suite/valuewrapper_opaque.i @@ -4,6 +4,10 @@ * Opaque types */ +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + %feature("valuewrapper") C; class C; diff --git a/Examples/test-suite/varargs_overload.i b/Examples/test-suite/varargs_overload.i index 9a24e15a8..eb9dcaab9 100644 --- a/Examples/test-suite/varargs_overload.i +++ b/Examples/test-suite/varargs_overload.i @@ -44,3 +44,47 @@ const char *vararg_over4(int i) { return buffer; } %} + + +// Same as above but non-vararg function declared first + +%inline %{ +const char *vararg_over6(int i) { + static char buffer[256]; + sprintf(buffer, "%d", i); + return buffer; +} +const char *vararg_over6(const char *fmt, ...) { + return fmt; +} + +const char *vararg_over7(int i, double j) { + static char buffer[256]; + sprintf(buffer, "%d %g", i, j); + return buffer; +} +const char *vararg_over7(const char *fmt, ...) { + return fmt; +} + +const char *vararg_over8(int i, double j, const char *s) { + static char buffer[256]; + sprintf(buffer, "%d %g %s", i, j, s); + return buffer; +} +const char *vararg_over8(const char *fmt, ...) { + return fmt; +} +%} + +%varargs(int mode = 0) vararg_over9; +%inline %{ +const char *vararg_over9(int i) { + static char buffer[256]; + sprintf(buffer, "%d", i); + return buffer; +} +const char *vararg_over9(const char *fmt, ...) { + return fmt; +} +%} diff --git a/Examples/test-suite/variable_replacement.i b/Examples/test-suite/variable_replacement.i new file mode 100644 index 000000000..d44ac1b96 --- /dev/null +++ b/Examples/test-suite/variable_replacement.i @@ -0,0 +1,16 @@ +%module variable_replacement + +%inline %{ + +class A { +public: + int a(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12) + { + return 0; + } +}; + +class B : public A { +}; + +%} diff --git a/Examples/test-suite/virtual_derivation.i b/Examples/test-suite/virtual_derivation.i index a199646d4..59b7fcea1 100644 --- a/Examples/test-suite/virtual_derivation.i +++ b/Examples/test-suite/virtual_derivation.i @@ -58,6 +58,7 @@ class IndexReader{ public: virtual void norms() = 0; + virtual ~IndexReader() {} }; class MultiReader : public IndexReader { diff --git a/Examples/test-suite/virtual_poly.i b/Examples/test-suite/virtual_poly.i index 5f2f1d201..8b500539e 100644 --- a/Examples/test-suite/virtual_poly.i +++ b/Examples/test-suite/virtual_poly.i @@ -13,6 +13,10 @@ #endif %} +#ifdef SWIGOCAML +%warnfilter(SWIGWARN_PARSE_KEYWORD) method; +#endif + // // Check this example with directors wherever possible. // diff --git a/Lib/allegrocl/allegrocl.swg b/Lib/allegrocl/allegrocl.swg index 152e5e6f0..524aa7c11 100644 --- a/Lib/allegrocl/allegrocl.swg +++ b/Lib/allegrocl/allegrocl.swg @@ -232,6 +232,8 @@ $body)" /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } /* name conversion for overloaded operators. */ #ifdef __cplusplus diff --git a/Lib/allegrocl/std_list.i b/Lib/allegrocl/std_list.i index 4e260897f..a3660c9f7 100644 --- a/Lib/allegrocl/std_list.i +++ b/Lib/allegrocl/std_list.i @@ -28,17 +28,20 @@ namespace std{ template class list { public: - - typedef T &reference; - typedef const T& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; typedef T &iterator; typedef const T& const_iterator; - + list(); list(unsigned int size, const T& value = T()); - list(const list &); + list(const list& other); - ~list(); void assign(unsigned int n, const T& value); void swap(list &x); @@ -46,21 +49,20 @@ namespace std{ const_reference back(); const_iterator begin(); const_iterator end(); - + void resize(unsigned int n, T c = T()); bool empty() const; void push_front(const T& INPUT); void push_back(const T& INPUT); - void pop_front(); void pop_back(); void clear(); unsigned int size() const; unsigned int max_size() const; void resize(unsigned int n, const T& INPUT); - + void remove(const T& INPUT); void unique(); void reverse(); @@ -153,7 +155,7 @@ namespace std{ if (j<0) j += size; if (i<0) i = 0; if (j>size) j = size; - + for (int k=0;ksize) j = size; - + for (int k=0;kinsert(self->end(),v.begin(),v.end()); } - } unsigned int __len__() { @@ -218,8 +219,7 @@ namespace std{ { self->pop_back(); } - - }; + } }; } diff --git a/Lib/allkw.swg b/Lib/allkw.swg index 563190e19..2d3cf6ea9 100644 --- a/Lib/allkw.swg +++ b/Lib/allkw.swg @@ -16,7 +16,6 @@ */ -%include %include %include %include @@ -25,7 +24,6 @@ %include %include %include -%include %include %include %include diff --git a/Lib/cdata.i b/Lib/cdata.i index 23e552cf9..3e16f31ec 100644 --- a/Lib/cdata.i +++ b/Lib/cdata.i @@ -43,18 +43,10 @@ typedef struct SWIGCDATA { $2 = $input->len; } -#elif SWIGCHICKEN +#elif SWIGPHP7 %typemap(out) SWIGCDATA { - C_word *string_space = C_alloc(C_SIZEOF_STRING($1.len)); - $result = C_string(&string_space, $1.len, $1.data); -} -%typemap(in) (const void *indata, int inlen) = (char *STRING, int LENGTH); - -#elif SWIGPHP - -%typemap(out) SWIGCDATA { - ZVAL_STRINGL($result, $1.data, $1.len, 1); + ZVAL_STRINGL($result, $1.data, $1.len); } %typemap(in) (const void *indata, int inlen) = (char *STRING, int LENGTH); @@ -86,8 +78,6 @@ static jbyteArray SWIG_JavaArrayOutCDATA(JNIEnv *jenv, char *result, jsize sz) { return $jnicall; } -#else -%echo "cdata.i module not supported." #endif diff --git a/Lib/cffi/cffi.swg b/Lib/cffi/cffi.swg index 3ad767ef8..f7294956f 100644 --- a/Lib/cffi/cffi.swg +++ b/Lib/cffi/cffi.swg @@ -136,6 +136,8 @@ /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } %{ diff --git a/Lib/chicken/chicken.swg b/Lib/chicken/chicken.swg index 17f0d0ac3..7df676754 100644 --- a/Lib/chicken/chicken.swg +++ b/Lib/chicken/chicken.swg @@ -11,8 +11,9 @@ #include %} -%insert(runtime) "swigrun.swg"; // Common C API type-checking code -%insert(runtime) "chickenrun.swg"; // CHICKEN run-time code +%insert(runtime) "swigrun.swg" // Common C API type-checking code +%insert(runtime) "swigerrors.swg" // SWIG errors +%insert(runtime) "chickenrun.swg" // CHICKEN run-time code /* ----------------------------------------------------------------------------- * standard typemaps @@ -617,7 +618,7 @@ $result = C_SCHEME_UNDEFINED; $1 = C_swig_is_string ($input); } -%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] { +%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE [] { void *ptr; $1 = !SWIG_ConvertPtr($input, &ptr, $1_descriptor, 0); } @@ -630,33 +631,30 @@ $result = C_SCHEME_UNDEFINED; %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE & { void *ptr = 0; - if (SWIG_ConvertPtr($input, &ptr, $descriptor, 0)) { - /* error */ + if (SWIG_ConvertPtr($input, &ptr, $descriptor, SWIG_POINTER_NO_NULL)) { $1 = 0; } else { - $1 = (ptr != 0); + $1 = 1; } } %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE && { void *ptr = 0; - if (SWIG_ConvertPtr($input, &ptr, $descriptor, 0)) { - /* error */ + if (SWIG_ConvertPtr($input, &ptr, $descriptor, SWIG_POINTER_NO_NULL)) { $1 = 0; } else { - $1 = (ptr != 0); + $1 = 1; } } %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { void *ptr = 0; - if (SWIG_ConvertPtr($input, &ptr, $&descriptor, 0)) { - /* error */ + if (SWIG_ConvertPtr($input, &ptr, $&descriptor, SWIG_POINTER_NO_NULL)) { $1 = 0; } else { - $1 = (ptr != 0); + $1 = 1; } } @@ -716,6 +714,8 @@ $result = C_SCHEME_UNDEFINED; /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } /* ------------------------------------------------------------ * Overloaded operator support diff --git a/Lib/chicken/chickenrun.swg b/Lib/chicken/chickenrun.swg index f13400181..bb14b4bc9 100644 --- a/Lib/chicken/chickenrun.swg +++ b/Lib/chicken/chickenrun.swg @@ -7,7 +7,7 @@ #include #include #include -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) +#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__BORLANDC__) || defined(_WATCOM) # ifndef snprintf # define snprintf _snprintf # endif @@ -265,6 +265,7 @@ SWIG_Chicken_ConvertPtr(C_word s, void **result, swig_type_info *type, int flags if (s == C_SCHEME_FALSE) { *result = NULL; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } else if (C_swig_is_swigpointer(s)) { /* try and convert type */ from = (swig_type_info *) C_block_item(s, 1); diff --git a/Lib/csharp/arrays_csharp.i b/Lib/csharp/arrays_csharp.i index 237067a88..861da8386 100644 --- a/Lib/csharp/arrays_csharp.i +++ b/Lib/csharp/arrays_csharp.i @@ -103,7 +103,47 @@ CSHARP_ARRAYS(long long, long) CSHARP_ARRAYS(unsigned long long, ulong) CSHARP_ARRAYS(float, float) CSHARP_ARRAYS(double, double) -CSHARP_ARRAYS(bool, bool) + +// By default C# will marshal bools as 4 bytes +// UnmanagedType.I1 will change this to 1 byte +// FIXME - When running on mono ArraySubType appears to be ignored and bools will be marshalled as 4-byte +// https://github.com/mono/mono/issues/15592 + +// input only arrays +%typemap(ctype) bool INPUT[] "bool*" +%typemap(cstype) bool INPUT[] "bool[]" +%typemap(imtype, inattributes="[global::System.Runtime.InteropServices.In, global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPArray,ArraySubType=System.Runtime.InteropServices.UnmanagedType.I1)]") bool INPUT[] "bool[]" +%typemap(csin) bool INPUT[] "$csinput" + +%typemap(in) bool INPUT[] %{ +$1 = $input; +%} +%typemap(freearg) bool INPUT[] "" +%typemap(argout) bool INPUT[] "" + +// output only arrays +%typemap(ctype) bool OUTPUT[] "bool*" +%typemap(cstype) bool OUTPUT[] "bool[]" +%typemap(imtype, inattributes="[global::System.Runtime.InteropServices.Out, global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPArray,ArraySubType=System.Runtime.InteropServices.UnmanagedType.I1)]") bool OUTPUT[] "bool[]" +%typemap(csin) bool OUTPUT[] "$csinput" + +%typemap(in) bool OUTPUT[] %{ +$1 = $input; +%} +%typemap(freearg) bool OUTPUT[] "" +%typemap(argout) bool OUTPUT[] "" + +// inout arrays +%typemap(ctype) bool INOUT[] "bool*" +%typemap(cstype) bool INOUT[] "bool[]" +%typemap(imtype, inattributes="[global::System.Runtime.InteropServices.In, global::System.Runtime.InteropServices.Out, global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPArray,ArraySubType=System.Runtime.InteropServices.UnmanagedType.I1)]") bool INOUT[] "bool[]" +%typemap(csin) bool INOUT[] "$csinput" + +%typemap(in) bool INOUT[] %{ +$1 = $input; +%} +%typemap(freearg) bool INOUT[] "" +%typemap(argout) bool INOUT[] "" %define CSHARP_ARRAYS_FIXED( CTYPE, CSTYPE ) diff --git a/Lib/csharp/boost_intrusive_ptr.i b/Lib/csharp/boost_intrusive_ptr.i index d0a048d16..fa3f53a20 100644 --- a/Lib/csharp/boost_intrusive_ptr.i +++ b/Lib/csharp/boost_intrusive_ptr.i @@ -314,7 +314,7 @@ } %} -%typemap(csdestruct, methodname="Dispose", methodmodifiers="public") TYPE { +%typemap(csdisposing, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") TYPE { lock(this) { if (swigCPtr.Handle != global::System.IntPtr.Zero) { if (swigCMemOwnBase) { @@ -323,11 +323,10 @@ } swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); } - global::System.GC.SuppressFinalize(this); } } -%typemap(csdestruct_derived, methodname="Dispose", methodmodifiers="public") TYPE { +%typemap(csdisposing_derived, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") TYPE { lock(this) { if (swigCPtr.Handle != global::System.IntPtr.Zero) { if (swigCMemOwnDerived) { @@ -336,8 +335,7 @@ } swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); } - global::System.GC.SuppressFinalize(this); - base.Dispose(); + base.Dispose(disposing); } } @@ -473,7 +471,7 @@ } %} -%typemap(csdestruct, methodname="Dispose", methodmodifiers="public") TYPE { +%typemap(csdisposing, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") TYPE { lock(this) { if (swigCPtr.Handle != global::System.IntPtr.Zero) { if (swigCMemOwnBase) { @@ -482,11 +480,10 @@ } swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); } - global::System.GC.SuppressFinalize(this); } } -%typemap(csdestruct_derived, methodname="Dispose", methodmodifiers="public") TYPE { +%typemap(csdisposing_derived, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") TYPE { lock(this) { if (swigCPtr.Handle != global::System.IntPtr.Zero) { if (swigCMemOwnDerived) { @@ -495,8 +492,7 @@ } swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); } - global::System.GC.SuppressFinalize(this); - base.Dispose(); + base.Dispose(disposing); } } @@ -505,6 +501,17 @@ %typemap(imtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast "global::System.Runtime.InteropServices.HandleRef" %typemap(imtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast "global::System.Runtime.InteropServices.HandleRef" +// Typecheck typemaps +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") + TYPE CONST, + TYPE CONST &, + TYPE CONST *, + TYPE *CONST&, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "" %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/csharp/boost_shared_ptr.i b/Lib/csharp/boost_shared_ptr.i index 2b65bf20d..508c0ec14 100644 --- a/Lib/csharp/boost_shared_ptr.i +++ b/Lib/csharp/boost_shared_ptr.i @@ -14,7 +14,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor mods -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -28,9 +28,21 @@ return $null; } $1 = *argp; %} -%typemap(out) CONST TYPE +%typemap(out) CONST TYPE %{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} +%typemap(directorin) CONST TYPE +%{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype((const $1_ltype &)$1)); %} + +%typemap(directorout) CONST TYPE +%{ if (!$input) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null $1_type", 0); + return $null; + } + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input; + $result = *smartarg->get(); +%} + // plain pointer %typemap(in, canthrow=1) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ smartarg = (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input; @@ -39,6 +51,13 @@ $result = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0; %} +%typemap(directorin) CONST TYPE * +%{ $input = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; %} + +%typemap(directorout) CONST TYPE * %{ +#error "typemaps for $1_type not available" +%} + // plain reference %typemap(in, canthrow=1) CONST TYPE & %{ $1 = ($1_ltype)(((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input) ? ((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input)->get() : 0); @@ -49,6 +68,13 @@ %typemap(out, fragment="SWIG_null_deleter") CONST TYPE & %{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner); %} +%typemap(directorin) CONST TYPE & +%{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (&$1 SWIG_NO_NULL_DELETER_0); %} + +%typemap(directorout) CONST TYPE & %{ +#error "typemaps for $1_type not available" +%} + // plain pointer by reference %typemap(in) TYPE *CONST& ($*1_ltype temp = 0) %{ temp = (TYPE *)(((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input) ? ((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input)->get() : 0); @@ -56,17 +82,41 @@ %typemap(out, fragment="SWIG_null_deleter") TYPE *CONST& %{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner); %} +%typemap(directorin) TYPE *CONST& +%{ $input = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; %} + +%typemap(directorout) TYPE *CONST& %{ +#error "typemaps for $1_type not available" +%} + // shared_ptr by value %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > %{ if ($input) $1 = *($&1_ltype)$input; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > %{ $result = $1 ? new $1_ltype($1) : 0; %} +%typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > +%{ $input = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > +%{ if ($input) { + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input; + $result = *smartarg; + } +%} + // shared_ptr by reference %typemap(in, canthrow=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & ($*1_ltype tempnull) %{ $1 = $input ? ($1_ltype)$input : &tempnull; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & -%{ $result = *$1 ? new $*1_ltype(*$1) : 0; %} +%{ $result = *$1 ? new $*1_ltype(*$1) : 0; %} + +%typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & +%{ $input = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{ +#error "typemaps for $1_type not available" +%} // shared_ptr by pointer %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * ($*1_ltype tempnull) @@ -75,12 +125,26 @@ %{ $result = ($1 && *$1) ? new $*1_ltype(*($1_ltype)$1) : 0; if ($owner) delete $1; %} +%typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * +%{ $input = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{ +#error "typemaps for $1_type not available" +%} + // shared_ptr by pointer reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempnull, $*1_ltype temp = 0) %{ temp = $input ? *($1_ltype)&$input : &tempnull; $1 = &temp; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& -%{ *($1_ltype)&$result = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %} +%{ *($1_ltype)&$result = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %} + +%typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& +%{ $input = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{ +#error "typemaps for $1_type not available" +%} // various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug %typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{ @@ -91,20 +155,20 @@ %} -%typemap (ctype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (ctype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "void *" -%typemap (imtype, out="global::System.IntPtr") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (imtype, out="global::System.IntPtr") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "global::System.Runtime.InteropServices.HandleRef" -%typemap (cstype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (cstype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(cstype, TYPE)" -%typemap(csin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap(csin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(cstype, TYPE).getCPtr($csinput)" @@ -175,6 +239,18 @@ return ret; } %} +%typemap(csdirectorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > "$typemap(cstype, TYPE).getCPtr($cscall).Handle" + +%typemap(csdirectorin) CONST TYPE, + CONST TYPE *, + CONST TYPE &, + TYPE *CONST& "($iminput == global::System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)($iminput, true)" + +%typemap(csdirectorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "($iminput == global::System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)($iminput, true)" + // Proxy classes (base classes, ie, not derived classes) %typemap(csbody) TYPE %{ @@ -206,7 +282,7 @@ } %} -%typemap(csdestruct, methodname="Dispose", methodmodifiers="public") TYPE { +%typemap(csdisposing, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") TYPE { lock(this) { if (swigCPtr.Handle != global::System.IntPtr.Zero) { if (swigCMemOwnBase) { @@ -215,11 +291,10 @@ } swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); } - global::System.GC.SuppressFinalize(this); } } -%typemap(csdestruct_derived, methodname="Dispose", methodmodifiers="public") TYPE { +%typemap(csdisposing_derived, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") TYPE { lock(this) { if (swigCPtr.Handle != global::System.IntPtr.Zero) { if (swigCMemOwnDerived) { @@ -228,11 +303,21 @@ } swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); } - global::System.GC.SuppressFinalize(this); - base.Dispose(); + base.Dispose(disposing); } } +// Typecheck typemaps +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") + TYPE CONST, + TYPE CONST &, + TYPE CONST *, + TYPE *CONST&, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "" + %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef - diff --git a/Lib/csharp/complex.i b/Lib/csharp/complex.i new file mode 100644 index 000000000..4a6f91cdf --- /dev/null +++ b/Lib/csharp/complex.i @@ -0,0 +1,5 @@ +#ifdef __cplusplus +%include +#else +#error C# module only supports complex in C++ mode. +#endif diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg index d94336194..832206386 100644 --- a/Lib/csharp/csharp.swg +++ b/Lib/csharp/csharp.swg @@ -843,11 +843,26 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { $*csclassname ret = (cPtr == global::System.IntPtr.Zero) ? null : new $*csclassname(cPtr, $owner);$excode return ret; } +%typemap(csvarout, excode=SWIGEXCODE) SWIGTYPE *const& %{ + get { + global::System.IntPtr cPtr = $imcall; + $*csclassname ret = (cPtr == global::System.IntPtr.Zero) ? null : new $*csclassname(cPtr, $owner);$excode + return ret; + } %} + %typemap(in) SWIGTYPE *const& ($*1_ltype temp = 0) %{ temp = ($*1_ltype)$input; $1 = ($1_ltype)&temp; %} %typemap(out) SWIGTYPE *const& %{ $result = (void *)*$1; %} +%typemap(directorin) SWIGTYPE *const& +%{ $input = (void *) $1; %} +%typemap(directorout, warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) SWIGTYPE *const& +%{ static $*1_ltype swig_temp; + swig_temp = ($*1_ltype)$input; + $result = &swig_temp; %} +%typemap(csdirectorin) SWIGTYPE *const& "($iminput == global::System.IntPtr.Zero) ? null : new $*csclassname($iminput, false)" +%typemap(csdirectorout) SWIGTYPE *const& "$*csclassname.getCPtr($cscall).Handle" /* Marshal C/C++ pointer to global::System.IntPtr */ %typemap(ctype) void *VOID_INT_PTR "void *" @@ -860,7 +875,8 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { global::System.IntPtr ret = $imcall;$excode return ret; } - +%typemap(csdirectorin) void *VOID_INT_PTR "$iminput" +%typemap(csdirectorout) void *VOID_INT_PTR "$cscall" /* Typemaps used for the generation of proxy and type wrapper class code */ %typemap(csbase) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) "" @@ -943,17 +959,24 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { SWIG_CSBODY_PROXY(internal, internal, SWIGTYPE) SWIG_CSBODY_TYPEWRAPPER(internal, protected, internal, SWIGTYPE) -%typemap(csfinalize) SWIGTYPE %{ +%typemap(csdispose) SWIGTYPE %{ ~$csclassname() { - Dispose(); + Dispose(false); + } + + public void Dispose() { + Dispose(true); + global::System.GC.SuppressFinalize(this); } %} +%typemap(csdispose_derived) SWIGTYPE "" + %typemap(csconstruct, excode=SWIGEXCODE,directorconnect="\n SwigDirectorConnect();") SWIGTYPE %{: this($imcall, true) {$excode$directorconnect } %} -%typemap(csdestruct, methodname="Dispose", methodmodifiers="public") SWIGTYPE { +%typemap(csdisposing, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") SWIGTYPE { lock(this) { if (swigCPtr.Handle != global::System.IntPtr.Zero) { if (swigCMemOwn) { @@ -962,11 +985,10 @@ SWIG_CSBODY_TYPEWRAPPER(internal, protected, internal, SWIGTYPE) } swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); } - global::System.GC.SuppressFinalize(this); } } -%typemap(csdestruct_derived, methodname="Dispose", methodmodifiers="public") SWIGTYPE { +%typemap(csdisposing_derived, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") SWIGTYPE { lock(this) { if (swigCPtr.Handle != global::System.IntPtr.Zero) { if (swigCMemOwn) { @@ -975,8 +997,7 @@ SWIG_CSBODY_TYPEWRAPPER(internal, protected, internal, SWIGTYPE) } swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); } - global::System.GC.SuppressFinalize(this); - base.Dispose(); + base.Dispose(disposing); } } @@ -994,6 +1015,7 @@ SWIG_CSBODY_TYPEWRAPPER(internal, protected, internal, SWIGTYPE) #define %csmethodmodifiers %feature("cs:methodmodifiers") #define %csnothrowexception %feature("except") #define %csattributes %feature("cs:attributes") +#define %proxycode %insert("proxycode") %pragma(csharp) imclassclassmodifiers="class" %pragma(csharp) moduleclassmodifiers="public class" @@ -1009,6 +1031,8 @@ SWIG_CSBODY_TYPEWRAPPER(internal, protected, internal, SWIGTYPE) /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } /* csharp keywords */ %include diff --git a/Lib/csharp/csharphead.swg b/Lib/csharp/csharphead.swg index 0b55635b3..7db4c0e3c 100644 --- a/Lib/csharp/csharphead.swg +++ b/Lib/csharp/csharphead.swg @@ -244,6 +244,7 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterExceptionArgumentCallbacks_$module( [global::System.ThreadStatic] private static global::System.Exception pendingException = null; private static int numExceptionsPending = 0; + private static global::System.Object exceptionsLock = null; public static bool Pending { get { @@ -259,7 +260,7 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterExceptionArgumentCallbacks_$module( if (pendingException != null) throw new global::System.ApplicationException("FATAL: An earlier pending exception from unmanaged code was missed and thus not thrown (" + pendingException.ToString() + ")", e); pendingException = e; - lock(typeof($imclassname)) { + lock(exceptionsLock) { numExceptionsPending++; } } @@ -270,13 +271,17 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterExceptionArgumentCallbacks_$module( if (pendingException != null) { e = pendingException; pendingException = null; - lock(typeof($imclassname)) { + lock(exceptionsLock) { numExceptionsPending--; } } } return e; } + + static SWIGPendingException() { + exceptionsLock = new global::System.Object(); + } } %} #endif // SWIG_CSHARP_NO_EXCEPTION_HELPER diff --git a/Lib/csharp/director.swg b/Lib/csharp/director.swg index 3438f2bf0..5d2ab5d9b 100644 --- a/Lib/csharp/director.swg +++ b/Lib/csharp/director.swg @@ -41,6 +41,10 @@ namespace Swig { public: DirectorPureVirtualException(const char *msg) : DirectorException(std::string("Attempt to invoke pure virtual method ") + msg) { } + + static void raise(const char *msg) { + throw DirectorPureVirtualException(msg); + } }; } diff --git a/Lib/csharp/std_array.i b/Lib/csharp/std_array.i new file mode 100644 index 000000000..a4f0f9640 --- /dev/null +++ b/Lib/csharp/std_array.i @@ -0,0 +1,227 @@ +/* ----------------------------------------------------------------------------- + * std_array.i + * + * SWIG typemaps for std::array + * C# implementation + * The C# wrapper is made to look and feel like a C# System.Collections.Generic.IReadOnlyList<> collection. + * ----------------------------------------------------------------------------- */ + +%{ +#include +#include +#include +%} + +%include + + +%define SWIG_STD_ARRAY_INTERNAL(T, N) +%typemap(csinterfaces) std::array< T, N > "global::System.IDisposable, global::System.Collections.IEnumerable\n , global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)>\n"; +%proxycode %{ + public $csclassname(global::System.Collections.ICollection c) : this() { + if (c == null) + throw new global::System.ArgumentNullException("c"); + int end = global::System.Math.Min(this.Count, c.Count); + int i = 0; + foreach ($typemap(cstype, T) elem in c) { + if (i >= end) + break; + this[i++] = elem; + } + } + + public int Count { + get { + return (int)size(); + } + } + + public $typemap(cstype, T) this[int index] { + get { + return getitem(index); + } + set { + setitem(index, value); + } + } + + public bool IsEmpty { + get { + return empty(); + } + } + + public void CopyTo($typemap(cstype, T)[] array) + { + CopyTo(0, array, 0, this.Count); + } + + public void CopyTo($typemap(cstype, T)[] array, int arrayIndex) + { + CopyTo(0, array, arrayIndex, this.Count); + } + + public void CopyTo(int index, $typemap(cstype, T)[] array, int arrayIndex, int count) + { + if (array == null) + throw new global::System.ArgumentNullException("array"); + if (index < 0) + throw new global::System.ArgumentOutOfRangeException("index", "Value is less than zero"); + if (arrayIndex < 0) + throw new global::System.ArgumentOutOfRangeException("arrayIndex", "Value is less than zero"); + if (count < 0) + throw new global::System.ArgumentOutOfRangeException("count", "Value is less than zero"); + if (array.Rank > 1) + throw new global::System.ArgumentException("Multi dimensional array.", "array"); + if (index+count > this.Count || arrayIndex+count > array.Length) + throw new global::System.ArgumentException("Number of elements to copy is too large."); + for (int i=0; i global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)>.GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + public $csclassnameEnumerator GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + // Type-safe enumerator + /// Note that the IEnumerator documentation requires an InvalidOperationException to be thrown + /// whenever the collection is modified. This has been done for changes in the size of the + /// collection but not when one of the elements of the collection is modified as it is a bit + /// tricky to detect unmanaged code that modifies the collection under our feet. + public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator + , global::System.Collections.Generic.IEnumerator<$typemap(cstype, T)> + { + private $csclassname collectionRef; + private int currentIndex; + private object currentObject; + private int currentSize; + + public $csclassnameEnumerator($csclassname collection) { + collectionRef = collection; + currentIndex = -1; + currentObject = null; + currentSize = collectionRef.Count; + } + + // Type-safe iterator Current + public $typemap(cstype, T) Current { + get { + if (currentIndex == -1) + throw new global::System.InvalidOperationException("Enumeration not started."); + if (currentIndex > currentSize - 1) + throw new global::System.InvalidOperationException("Enumeration finished."); + if (currentObject == null) + throw new global::System.InvalidOperationException("Collection modified."); + return ($typemap(cstype, T))currentObject; + } + } + + // Type-unsafe IEnumerator.Current + object global::System.Collections.IEnumerator.Current { + get { + return Current; + } + } + + public bool MoveNext() { + int size = collectionRef.Count; + bool moveOkay = (currentIndex+1 < size) && (size == currentSize); + if (moveOkay) { + currentIndex++; + currentObject = collectionRef[currentIndex]; + } else { + currentObject = null; + } + return moveOkay; + } + + public void Reset() { + currentIndex = -1; + currentObject = null; + if (collectionRef.Count != currentSize) { + throw new global::System.InvalidOperationException("Collection modified."); + } + } + + public void Dispose() { + currentIndex = -1; + currentObject = null; + } + } +%} + + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + array(); + array(const array &other); + + size_type size() const; + bool empty() const; + + %rename(Fill) fill; + void fill(const value_type& value); + + %rename(Swap) swap; + void swap(array& other); + + %extend { + T getitemcopy(int index) throw (std::out_of_range) { + if (index>=0 && index<(int)$self->size()) + return (*$self)[index]; + else + throw std::out_of_range("index"); + } + const_reference getitem(int index) throw (std::out_of_range) { + if (index>=0 && index<(int)$self->size()) + return (*$self)[index]; + else + throw std::out_of_range("index"); + } + void setitem(int index, const_reference val) throw (std::out_of_range) { + if (index>=0 && index<(int)$self->size()) + (*$self)[index] = val; + else + throw std::out_of_range("index"); + } + void Reverse() { + std::reverse($self->begin(), $self->end()); + } + void Reverse(int index, int count) throw (std::out_of_range, std::invalid_argument) { + if (index < 0) + throw std::out_of_range("index"); + if (count < 0) + throw std::out_of_range("count"); + if (index >= (int)$self->size()+1 || index+count > (int)$self->size()) + throw std::invalid_argument("invalid range"); + std::reverse($self->begin()+index, $self->begin()+index+count); + } + } +%enddef + + +%csmethodmodifiers std::array::empty "private" +%csmethodmodifiers std::array::getitemcopy "private" +%csmethodmodifiers std::array::getitem "private" +%csmethodmodifiers std::array::setitem "private" +%csmethodmodifiers std::array::size "private" + +namespace std { + template class array { + SWIG_STD_ARRAY_INTERNAL(T, N) + }; +} diff --git a/Lib/csharp/std_complex.i b/Lib/csharp/std_complex.i new file mode 100644 index 000000000..6a0cc5458 --- /dev/null +++ b/Lib/csharp/std_complex.i @@ -0,0 +1,95 @@ +/* ----------------------------------------------------------------------------- + * std_complex.i + * + * Typemaps for handling std::complex and std::complex as a .NET + * System.Numerics.Complex type. Requires .NET 4 minimum. + * ----------------------------------------------------------------------------- */ + +%{ +#include +%} + +%fragment("SwigSystemNumericsComplex", "header") { +extern "C" { +// Identical to the layout of System.Numerics.Complex, but does assume that it is +// LayoutKind.Sequential on the managed side +struct SwigSystemNumericsComplex { + double real; + double imag; +}; +} + +SWIGINTERN SwigSystemNumericsComplex SwigCreateSystemNumericsComplex(double real, double imag) { + SwigSystemNumericsComplex cpx; + cpx.real = real; + cpx.imag = imag; + return cpx; +} +} + +namespace std { + +%naturalvar complex; + +template +class complex +{ +public: + complex(T re = T(), T im = T()); +}; + +} + +%define SWIG_COMPLEX_TYPEMAPS(T) +%typemap(ctype, fragment="SwigSystemNumericsComplex") std::complex, const std::complex & "SwigSystemNumericsComplex" +%typemap(imtype) std::complex, const std::complex & "System.Numerics.Complex" +%typemap(cstype) std::complex, const std::complex & "System.Numerics.Complex" + +%typemap(in) std::complex +%{$1 = std::complex< double >($input.real, $input.imag);%} + +%typemap(in) const std::complex &($*1_ltype temp) +%{temp = std::complex< T >((T)$input.real, (T)$input.imag); + $1 = &temp;%} + +%typemap(out, null="SwigCreateSystemNumericsComplex(0.0, 0.0)") std::complex +%{$result = SwigCreateSystemNumericsComplex($1.real(), $1.imag());%} + +%typemap(out, null="SwigCreateSystemNumericsComplex(0.0, 0.0)") const std::complex & +%{$result = SwigCreateSystemNumericsComplex($1->real(), $1->imag());%} + +%typemap(cstype) std::complex, const std::complex & "System.Numerics.Complex" + +%typemap(csin) std::complex, const std::complex & "$csinput" + +%typemap(csout, excode=SWIGEXCODE) std::complex, const std::complex & { + System.Numerics.Complex ret = $imcall;$excode + return ret; + } + +%typemap(csvarin, excode=SWIGEXCODE2) const std::complex & %{ + set { + $imcall;$excode + } + %} + +%typemap(csvarout, excode=SWIGEXCODE2) const std::complex & %{ + get { + System.Numerics.Complex ret = $imcall;$excode + return ret; + } + %} + +%template() std::complex; +%enddef + +// By default, typemaps for both std::complex and std::complex +// are defined, but one of them can be disabled by predefining the +// corresponding symbol before including this file. +#ifndef SWIG_NO_STD_COMPLEX_DOUBLE +SWIG_COMPLEX_TYPEMAPS(double) +#endif + +#ifndef SWIG_NO_STD_COMPLEX_FLOAT +SWIG_COMPLEX_TYPEMAPS(float) +#endif diff --git a/Lib/csharp/std_except.i b/Lib/csharp/std_except.i index 27eb84bc2..c983bd0f6 100644 --- a/Lib/csharp/std_except.i +++ b/Lib/csharp/std_except.i @@ -7,6 +7,7 @@ * ----------------------------------------------------------------------------- */ %{ +#include #include %} @@ -16,6 +17,7 @@ namespace std struct exception {}; } +%typemap(throws, canthrow=1) std::bad_cast "SWIG_CSharpSetPendingException(SWIG_CSharpInvalidCastException, $1.what());\n return $null;" %typemap(throws, canthrow=1) std::bad_exception "SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, $1.what());\n return $null;" %typemap(throws, canthrow=1) std::domain_error "SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, $1.what());\n return $null;" %typemap(throws, canthrow=1) std::exception "SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, $1.what());\n return $null;" diff --git a/Lib/csharp/std_list.i b/Lib/csharp/std_list.i new file mode 100644 index 000000000..674aba0ab --- /dev/null +++ b/Lib/csharp/std_list.i @@ -0,0 +1,519 @@ +/* ----------------------------------------------------------------------------- + * std_list.i + * + * SWIG typemaps for std::list + * C# implementation + * The C# wrapper is made to look and feel like a C# System.Collections.Generic.LinkedList<> collection. + * + * Note that IEnumerable<> is implemented in the proxy class which is useful for using LINQ with + * C++ std::list wrappers. The ICollection<> interface is also implemented to provide enhanced functionality + * whenever we are confident that the required C++ operator== is available. This is the case for when + * T is a primitive type or a pointer. If T does define an operator==, then use the SWIG_STD_LIST_ENHANCED + * macro to obtain this enhanced functionality, for example: + * + * SWIG_STD_LIST_ENHANCED(SomeNamespace::Klass) + * %template(ListKlass) std::list; + * ----------------------------------------------------------------------------- */ + +%include + +// MACRO for use within the std::list class body +%define SWIG_STD_LIST_MINIMUM_INTERNAL(CSINTERFACE, CTYPE...) +%typemap(csinterfaces) std::list< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable, global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n"; + +%apply void *VOID_INT_PTR { std::list< CTYPE >::iterator * }; + +%proxycode %{ + public $csclassname(global::System.Collections.IEnumerable c) : this() { + if (c == null) + throw new global::System.ArgumentNullException("c"); + foreach ($typemap(cstype, CTYPE) element in c) { + this.AddLast(element); + } + } + + public bool IsReadOnly { + get { + return false; + } + } + + public int Count { + get { + return (int)size(); + } + } + + public $csclassnameNode First { + get { + if (Count == 0) + return null; + return new $csclassnameNode(getFirstIter(), this); + } + } + + public $csclassnameNode Last { + get { + if (Count == 0) + return null; + return new $csclassnameNode(getLastIter(), this); + } + } + + public $csclassnameNode AddFirst($typemap(cstype, CTYPE) value) { + push_front(value); + return new $csclassnameNode(getFirstIter(), this); + } + + public void AddFirst($csclassnameNode newNode) { + ValidateNewNode(newNode); + if (!newNode.inlist) { + push_front(newNode.csharpvalue); + newNode.iter = getFirstIter(); + newNode.inlist = true; + } else { + throw new global::System.InvalidOperationException("The " + newNode.GetType().Name + " node already belongs to a " + this.GetType().Name); + } + } + + public $csclassnameNode AddLast($typemap(cstype, CTYPE) value) { + push_back(value); + return new $csclassnameNode(getLastIter(), this); + } + + public void AddLast($csclassnameNode newNode) { + ValidateNewNode(newNode); + if (!newNode.inlist) { + push_back(newNode.csharpvalue); + newNode.iter = getLastIter(); + newNode.inlist = true; + } else { + throw new global::System.InvalidOperationException("The " + newNode.GetType().Name + " node already belongs to a " + this.GetType().Name); + } + } + + public $csclassnameNode AddBefore($csclassnameNode node, $typemap(cstype, CTYPE) value) { + return new $csclassnameNode(insertNode(node.iter, value), this); + } + + public void AddBefore($csclassnameNode node, $csclassnameNode newNode) { + ValidateNode(node); + ValidateNewNode(newNode); + if (!newNode.inlist) { + newNode.iter = insertNode(node.iter, newNode.csharpvalue); + newNode.inlist = true; + } else { + throw new global::System.InvalidOperationException("The " + newNode.GetType().Name + " node already belongs to a " + this.GetType().Name); + } + } + + public $csclassnameNode AddAfter($csclassnameNode node, $typemap(cstype, CTYPE) value) { + node = node.Next; + return new $csclassnameNode(insertNode(node.iter, value), this); + } + + public void AddAfter($csclassnameNode node, $csclassnameNode newNode) { + ValidateNode(node); + ValidateNewNode(newNode); + if (!newNode.inlist) { + if (node == this.Last) + AddLast(newNode); + else + { + node = node.Next; + newNode.iter = insertNode(node.iter, newNode.csharpvalue); + newNode.inlist = true; + } + } else { + throw new global::System.InvalidOperationException("The " + newNode.GetType().Name + " node already belongs to a " + this.GetType().Name); + } + } + + public void Add($typemap(cstype, CTYPE) value) { + AddLast(value); + } + + public void Remove($csclassnameNode node) { + ValidateNode(node); + eraseIter(node.iter); + } + + public void CopyTo($typemap(cstype, CTYPE)[] array, int index) { + if (array == null) + throw new global::System.ArgumentNullException("array"); + if (index < 0 || index > array.Length) + throw new global::System.ArgumentOutOfRangeException("index", "Value is less than zero"); + if (array.Rank > 1) + throw new global::System.ArgumentException("Multi dimensional array.", "array"); + $csclassnameNode node = this.First; + if (node != null) { + do { + array[index++] = node.Value; + node = node.Next; + } while (node != null); + } + } + + internal void ValidateNode($csclassnameNode node) { + if (node == null) { + throw new System.ArgumentNullException("node"); + } + if (!node.inlist || node.list != this) { + throw new System.InvalidOperationException("node"); + } + } + + internal void ValidateNewNode($csclassnameNode node) { + if (node == null) { + throw new System.ArgumentNullException("node"); + } + } + + global::System.Collections.Generic.IEnumerator<$typemap(cstype, CTYPE)> global::System.Collections.Generic.IEnumerable<$typemap(cstype, CTYPE)>.GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + public $csclassnameEnumerator GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator, + global::System.Collections.Generic.IEnumerator<$typemap(cstype, CTYPE)> + { + private $csclassname collectionRef; + private $csclassnameNode currentNode; + private int currentIndex; + private object currentObject; + private int currentSize; + + public $csclassnameEnumerator($csclassname collection) { + collectionRef = collection; + currentNode = collection.First; + currentIndex = 0; + currentObject = null; + currentSize = collectionRef.Count; + } + + // Type-safe iterator Current + public $typemap(cstype, CTYPE) Current { + get { + if (currentIndex == -1) + throw new global::System.InvalidOperationException("Enumeration not started."); + if (currentIndex > currentSize) + throw new global::System.InvalidOperationException("Enumeration finished."); + if (currentObject == null) + throw new global::System.InvalidOperationException("Collection modified."); + return ($typemap(cstype, CTYPE))currentObject; + } + } + + // Type-unsafe IEnumerator.Current + object global::System.Collections.IEnumerator.Current { + get { + return Current; + } + } + + public bool MoveNext() { + if (currentNode == null) { + currentIndex = collectionRef.Count + 1; + return false; + } + ++currentIndex; + currentObject = currentNode.Value; + currentNode = currentNode.Next; + return true; + } + + public void Reset() { + currentIndex = -1; + currentObject = null; + if (collectionRef.Count != currentSize) { + throw new global::System.InvalidOperationException("Collection modified."); + } + } + + public void Dispose() { + currentIndex = -1; + currentObject = null; + } + } + + public sealed class $csclassnameNode { + internal $csclassname list; + internal System.IntPtr iter; + internal $typemap(cstype, CTYPE) csharpvalue; + internal bool inlist; + + public $csclassnameNode($typemap(cstype, CTYPE) value) { + csharpvalue = value; + inlist = false; + } + + internal $csclassnameNode(System.IntPtr iter, $csclassname list) { + this.list = list; + this.iter = iter; + inlist = true; + } + + public $csclassname List { + get { + return this.list; + } + } + + public $csclassnameNode Next { + get { + if (list.getNextIter(iter) == System.IntPtr.Zero) + return null; + return new $csclassnameNode(list.getNextIter(iter), list); + } + } + + public $csclassnameNode Previous { + get { + if (list.getPrevIter(iter) == System.IntPtr.Zero) + return null; + return new $csclassnameNode(list.getPrevIter(iter), list); + } + } + + public $typemap(cstype, CTYPE) Value { + get { + return list.getItem(this.iter); + } + set { + list.setItem(this.iter, value); + } + } + + public static bool operator==($csclassnameNode node1, $csclassnameNode node2) { + if (object.ReferenceEquals(node1, null) && object.ReferenceEquals(node2, null)) + return true; + if (object.ReferenceEquals(node1, null) || object.ReferenceEquals(node2, null)) + return false; + return node1.Equals(node2); + } + + public static bool operator!=($csclassnameNode node1, $csclassnameNode node2) { + if (node1 == null && node2 == null) + return false; + if (node1 == null || node2 == null) + return true; + return !node1.Equals(node2); + } + + public bool Equals($csclassnameNode node) { + if (node == null) + return false; + if (!node.inlist || !this.inlist) + return object.ReferenceEquals(this, node); + return list.equals(this.iter, node.iter); + } + + public override bool Equals(object node) { + return Equals(($csclassnameNode)node); + } + + public override int GetHashCode() { + int hash = 13; + if (inlist) { + hash = (hash * 7) + this.list.GetHashCode(); + hash = (hash * 7) + this.Value.GetHashCode(); + hash = (hash * 7) + this.list.getNextIter(this.iter).GetHashCode(); + hash = (hash * 7) + this.list.getPrevIter(this.iter).GetHashCode(); + } else { + hash = (hash * 7) + this.csharpvalue.GetHashCode(); + } + return hash; + } + + public void Dispose() { + list.deleteIter(this.iter); + } + } +%} + +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef CTYPE value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + class iterator; + + void push_front(CTYPE const& x); + void push_back(CTYPE const& x); + %rename(RemoveFirst) pop_front; + void pop_front(); + %rename(RemoveLast) pop_back; + void pop_back(); + size_type size() const; + %rename(Clear) clear; + void clear(); + %extend { + const_reference getItem(iterator *iter) { + return **iter; + } + + void setItem(iterator *iter, CTYPE const& val) { + *(*iter) = val; + } + + iterator *getFirstIter() { + if ($self->size() == 0) + return NULL; + return new std::list< CTYPE >::iterator($self->begin()); + } + + iterator *getLastIter() { + if ($self->size() == 0) + return NULL; + return new std::list< CTYPE >::iterator(--$self->end()); + } + + iterator *getNextIter(iterator *iter) { + std::list< CTYPE >::iterator it = *iter; + if (std::distance(it, --$self->end()) != 0) { + std::list< CTYPE >::iterator* itnext = new std::list< CTYPE >::iterator(++it); + return itnext; + } + return NULL; + } + + iterator *getPrevIter(iterator *iter) { + std::list< CTYPE >::iterator it = *iter; + if (std::distance($self->begin(), it) != 0) { + std::list< CTYPE >::iterator* itprev = new std::list< CTYPE >::iterator(--it); + return itprev; + } + return NULL; + } + + iterator *insertNode(iterator *iter, CTYPE const& value) { + std::list< CTYPE >::iterator it = $self->insert(*iter, value); + return new std::list< CTYPE >::iterator(it); + } + + void eraseIter(iterator *iter) { + std::list< CTYPE >::iterator it = *iter; + $self->erase(it); + } + + void deleteIter(iterator *iter) { + delete iter; + } + + bool equals(iterator *iter1, iterator *iter2) { + if (iter1 == NULL && iter2 == NULL) + return true; + std::list< CTYPE >::iterator it1 = *iter1; + std::list< CTYPE >::iterator it2 = *iter2; + return it1 == it2; + } + } +%enddef + +// Extra methods added to the collection class if operator== is defined for the class being wrapped +// The class will then implement ICollection<>, which adds extra functionality +%define SWIG_STD_LIST_EXTRA_OP_EQUALS_EQUALS(CTYPE...) + %extend { + bool Contains(CTYPE const& value) { + return std::find($self->begin(), $self->end(), value) != $self->end(); + } + + bool Remove(CTYPE const& value) { + std::list< CTYPE >::iterator it = std::find($self->begin(), $self->end(), value); + if (it != $self->end()) { + $self->erase(it); + return true; + } + return false; + } + + iterator *find(CTYPE const& value) { + if (std::find($self->begin(), $self->end(), value) != $self->end()) { + return new std::list< CTYPE >::iterator(std::find($self->begin(), $self->end(), value)); + } + return NULL; + } + } +%proxycode %{ + public $csclassnameNode Find($typemap(cstype, CTYPE) value) { + System.IntPtr tmp = find(value); + if (tmp != System.IntPtr.Zero) { + return new $csclassnameNode(tmp, this); + } + return null; + } +%} +%enddef + +// Macros for std::list class specializations/enhancements +%define SWIG_STD_LIST_ENHANCED(CTYPE...) +namespace std { + template<> class list< CTYPE > { + SWIG_STD_LIST_MINIMUM_INTERNAL(ICollection, %arg(CTYPE)); + SWIG_STD_LIST_EXTRA_OP_EQUALS_EQUALS(CTYPE) + }; +} +%enddef + + +%{ +#include +#include +#include +%} + +%csmethodmodifiers std::list::size "private" +%csmethodmodifiers std::list::getItem "private" +%csmethodmodifiers std::list::setItem "private" +%csmethodmodifiers std::list::push_front "private" +%csmethodmodifiers std::list::push_back "private" +%csmethodmodifiers std::list::getFirstIter "private" +%csmethodmodifiers std::list::getNextIter "private" +%csmethodmodifiers std::list::getPrevIter "private" +%csmethodmodifiers std::list::getLastIter "private" +%csmethodmodifiers std::list::find "private" +%csmethodmodifiers std::list::deleteIter "private" + +namespace std { + // primary (unspecialized) class template for std::list + // does not require operator== to be defined + template + class list { + SWIG_STD_LIST_MINIMUM_INTERNAL(IEnumerable, T) + }; + // specialization for pointers + template + class list { + SWIG_STD_LIST_MINIMUM_INTERNAL(ICollection, T *) + SWIG_STD_LIST_EXTRA_OP_EQUALS_EQUALS(T *) + }; +} + +// template specializations for std::list +// these provide extra collections methods as operator== is defined +SWIG_STD_LIST_ENHANCED(char) +SWIG_STD_LIST_ENHANCED(signed char) +SWIG_STD_LIST_ENHANCED(unsigned char) +SWIG_STD_LIST_ENHANCED(short) +SWIG_STD_LIST_ENHANCED(unsigned short) +SWIG_STD_LIST_ENHANCED(int) +SWIG_STD_LIST_ENHANCED(unsigned int) +SWIG_STD_LIST_ENHANCED(long) +SWIG_STD_LIST_ENHANCED(unsigned long) +SWIG_STD_LIST_ENHANCED(long long) +SWIG_STD_LIST_ENHANCED(unsigned long long) +SWIG_STD_LIST_ENHANCED(float) +SWIG_STD_LIST_ENHANCED(double) +SWIG_STD_LIST_ENHANCED(std::string) // also requires a %include +SWIG_STD_LIST_ENHANCED(std::wstring) // also requires a %include diff --git a/Lib/csharp/std_map.i b/Lib/csharp/std_map.i index db6fa7bd1..e538a03a1 100644 --- a/Lib/csharp/std_map.i +++ b/Lib/csharp/std_map.i @@ -4,14 +4,14 @@ * SWIG typemaps for std::map< K, T, C > * * The C# wrapper is made to look and feel like a C# System.Collections.Generic.IDictionary<>. - * + * * Using this wrapper is fairly simple. For example, to create a map from integers to doubles use: * * %include * %template(MapIntDouble) std::map * * Notes: - * 1) IEnumerable<> is implemented in the proxy class which is useful for using LINQ with + * 1) IEnumerable<> is implemented in the proxy class which is useful for using LINQ with * C++ std::map wrappers. * * Warning: heavy macro usage in this file. Use swig -E to get a sane view on the real file contents! @@ -27,7 +27,7 @@ %define SWIG_STD_MAP_INTERNAL(K, T, C) %typemap(csinterfaces) std::map< K, T, C > "global::System.IDisposable \n , global::System.Collections.Generic.IDictionary<$typemap(cstype, K), $typemap(cstype, T)>\n"; -%typemap(cscode) std::map %{ +%proxycode %{ public $typemap(cstype, T) this[$typemap(cstype, K) key] { get { @@ -55,8 +55,8 @@ } public bool IsReadOnly { - get { - return false; + get { + return false; } } @@ -84,7 +84,7 @@ return vals; } } - + public void Add(global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) { Add(item.Key, item.Value); } @@ -143,7 +143,7 @@ /// whenever the collection is modified. This has been done for changes in the size of the /// collection but not when one of the elements of the collection is modified as it is a bit /// tricky to detect unmanaged code that modifies the collection under our feet. - public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator, + public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator, global::System.Collections.Generic.IEnumerator> { private $csclassname collectionRef; @@ -206,7 +206,7 @@ currentObject = null; } } - + %} public: @@ -214,9 +214,14 @@ typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; map(); - map(const map< K, T, C > &other); + map(const map& other); size_type size() const; bool empty() const; %rename(Clear) clear; @@ -239,11 +244,11 @@ return iter != $self->end(); } - void Add(const key_type& key, const mapped_type& val) throw (std::out_of_range) { + void Add(const key_type& key, const mapped_type& value) throw (std::out_of_range) { std::map< K, T, C >::iterator iter = $self->find(key); if (iter != $self->end()) throw std::out_of_range("key already exists"); - $self->insert(std::pair< K, T >(key, val)); + $self->insert(std::pair< K, T >(key, value)); } bool Remove(const key_type& key) { @@ -251,7 +256,7 @@ if (iter != $self->end()) { $self->erase(iter); return true; - } + } return false; } @@ -285,12 +290,12 @@ %csmethodmodifiers std::map::destroy_iterator "private" // Default implementation -namespace std { +namespace std { template > class map { SWIG_STD_MAP_INTERNAL(K, T, C) }; } - + // Legacy macros (deprecated) %define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) diff --git a/Lib/csharp/std_pair.i b/Lib/csharp/std_pair.i index 0712ad762..732347db5 100644 --- a/Lib/csharp/std_pair.i +++ b/Lib/csharp/std_pair.i @@ -18,12 +18,14 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; pair(); - pair(T t, U u); - pair(const pair& p); + pair(T first, U second); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/csharp/std_set.i b/Lib/csharp/std_set.i new file mode 100644 index 000000000..82f010aff --- /dev/null +++ b/Lib/csharp/std_set.i @@ -0,0 +1,311 @@ +/* ----------------------------------------------------------------------------- + * std_set.i + * + * SWIG typemaps for std::set. + * + * Note that ISet<> used here requires .NET 4 or later. + * + * The C# wrapper implements ISet<> interface and shares performance + * characteristics of C# System.Collections.Generic.SortedSet<> class, but + * doesn't provide quite all of its methods. + * ----------------------------------------------------------------------------- */ + +%{ +#include +#include +#include +%} + +%csmethodmodifiers std::set::size "private" +%csmethodmodifiers std::set::getitem "private" +%csmethodmodifiers std::set::create_iterator_begin "private" +%csmethodmodifiers std::set::get_next "private" +%csmethodmodifiers std::set::destroy_iterator "private" + +namespace std { + +// TODO: Add support for comparator and allocator template parameters. +template +class set { + +%typemap(csinterfaces) std::set "global::System.IDisposable, global::System.Collections.Generic.ISet<$typemap(cstype, T)>\n"; +%proxycode %{ + void global::System.Collections.Generic.ICollection<$typemap(cstype, T)>.Add($typemap(cstype, T) item) { + ((global::System.Collections.Generic.ISet<$typemap(cstype, T)>)this).Add(item); + } + + public bool TryGetValue($typemap(cstype, T) equalValue, out $typemap(cstype, T) actualValue) { + try { + actualValue = getitem(equalValue); + return true; + } catch { + actualValue = default($typemap(cstype, T)); + return false; + } + } + + public int Count { + get { + return (int)size(); + } + } + + public bool IsReadOnly { + get { + return false; + } + } + + public void CopyTo($typemap(cstype, T)[] array) { + CopyTo(array, 0); + } + + public void CopyTo($typemap(cstype, T)[] array, int arrayIndex) { + if (array == null) + throw new global::System.ArgumentNullException("array"); + if (arrayIndex < 0) + throw new global::System.ArgumentOutOfRangeException("arrayIndex", "Value is less than zero"); + if (array.Rank > 1) + throw new global::System.ArgumentException("Multi dimensional array.", "array"); + if (arrayIndex+this.Count > array.Length) + throw new global::System.ArgumentException("Number of elements to copy is too large."); + + foreach ($typemap(cstype, T) item in this) { + array.SetValue(item, arrayIndex++); + } + } + + public void ExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + Remove(item); + } + } + + public void IntersectWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + $csclassname old = new $csclassname(this); + + Clear(); + foreach ($typemap(cstype, T) item in other) { + if (old.Contains(item)) + Add(item); + } + } + + private static int count_enum(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + int count = 0; + foreach ($typemap(cstype, T) item in other) { + count++; + } + + return count; + } + + public bool IsProperSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + return IsSubsetOf(other) && Count < count_enum(other); + } + + public bool IsProperSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + return IsSupersetOf(other) && Count > count_enum(other); + } + + public bool IsSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + int countContained = 0; + + foreach ($typemap(cstype, T) item in other) { + if (Contains(item)) + countContained++; + } + + return countContained == Count; + } + + public bool IsSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + if (!Contains(item)) + return false; + } + + return true; + } + + public bool Overlaps(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + if (Contains(item)) + return true; + } + + return false; + } + + public bool SetEquals(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + return IsSupersetOf(other) && Count == count_enum(other); + } + + public void SymmetricExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + if (!Remove(item)) + Add(item); + } + } + + public void UnionWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + Add(item); + } + } + + private global::System.Collections.Generic.ICollection<$typemap(cstype, T)> Items { + get { + global::System.Collections.Generic.ICollection<$typemap(cstype, T)> items = new global::System.Collections.Generic.List<$typemap(cstype, T)>(); + int size = this.Count; + if (size > 0) { + global::System.IntPtr iter = create_iterator_begin(); + for (int i = 0; i < size; i++) { + items.Add(get_next(iter)); + } + destroy_iterator(iter); + } + return items; + } + } + + global::System.Collections.Generic.IEnumerator<$typemap(cstype, T)> global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)>.GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + public $csclassnameEnumerator GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + // Type-safe enumerator + /// Note that the IEnumerator documentation requires an InvalidOperationException to be thrown + /// whenever the collection is modified. This has been done for changes in the size of the + /// collection but not when one of the elements of the collection is modified as it is a bit + /// tricky to detect unmanaged code that modifies the collection under our feet. + public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator, + global::System.Collections.Generic.IEnumerator<$typemap(cstype, T)> + { + private $csclassname collectionRef; + private global::System.Collections.Generic.IList<$typemap(cstype, T)> ItemsCollection; + private int currentIndex; + private object currentObject; + private int currentSize; + + public $csclassnameEnumerator($csclassname collection) { + collectionRef = collection; + ItemsCollection = new global::System.Collections.Generic.List<$typemap(cstype, T)>(collection.Items); + currentIndex = -1; + currentObject = null; + currentSize = collectionRef.Count; + } + + // Type-safe iterator Current + public $typemap(cstype, T) Current { + get { + if (currentIndex == -1) + throw new global::System.InvalidOperationException("Enumeration not started."); + if (currentIndex > currentSize - 1) + throw new global::System.InvalidOperationException("Enumeration finished."); + if (currentObject == null) + throw new global::System.InvalidOperationException("Collection modified."); + return ($typemap(cstype, T))currentObject; + } + } + + // Type-unsafe IEnumerator.Current + object global::System.Collections.IEnumerator.Current { + get { + return Current; + } + } + + public bool MoveNext() { + int size = collectionRef.Count; + bool moveOkay = (currentIndex+1 < size) && (size == currentSize); + if (moveOkay) { + currentIndex++; + currentObject = ItemsCollection[currentIndex]; + } else { + currentObject = null; + } + return moveOkay; + } + + public void Reset() { + currentIndex = -1; + currentObject = null; + if (collectionRef.Count != currentSize) { + throw new global::System.InvalidOperationException("Collection modified."); + } + } + + public void Dispose() { + currentIndex = -1; + currentObject = null; + } + } + +%} + + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T key_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + set(); + set(const set& other); + size_type size() const; + bool empty() const; + %rename(Clear) clear; + void clear(); + %extend { + bool Add(const value_type& item) { + return $self->insert(item).second; + } + + bool Contains(const value_type& item) { + return $self->count(item) != 0; + } + + bool Remove(const value_type& item) { + return $self->erase(item) != 0; + } + + const value_type& getitem(const value_type& item) throw (std::out_of_range) { + std::set::iterator iter = $self->find(item); + if (iter == $self->end()) + throw std::out_of_range("item not found"); + + return *iter; + } + + // create_iterator_begin(), get_next() and destroy_iterator work together to provide a collection of items to C# + %apply void *VOID_INT_PTR { std::set::iterator *create_iterator_begin } + %apply void *VOID_INT_PTR { std::set::iterator *swigiterator } + + std::set::iterator *create_iterator_begin() { + return new std::set::iterator($self->begin()); + } + + const key_type& get_next(std::set::iterator *swigiterator) { + std::set::iterator iter = *swigiterator; + (*swigiterator)++; + return *iter; + } + + void destroy_iterator(std::set::iterator *swigiterator) { + delete swigiterator; + } + } +}; + +} diff --git a/Lib/csharp/std_vector.i b/Lib/csharp/std_vector.i index 467a2ade8..e2811290c 100644 --- a/Lib/csharp/std_vector.i +++ b/Lib/csharp/std_vector.i @@ -5,28 +5,31 @@ * C# implementation * The C# wrapper is made to look and feel like a C# System.Collections.Generic.List<> collection. * - * Note that IEnumerable<> is implemented in the proxy class which is useful for using LINQ with + * Note that IEnumerable<> is implemented in the proxy class which is useful for using LINQ with * C++ std::vector wrappers. The IList<> interface is also implemented to provide enhanced functionality - * whenever we are confident that the required C++ operator== is available. This is the case for when + * whenever we are confident that the required C++ operator== is available. This is the case for when * T is a primitive type or a pointer. If T does define an operator==, then use the SWIG_STD_VECTOR_ENHANCED * macro to obtain this enhanced functionality, for example: * * SWIG_STD_VECTOR_ENHANCED(SomeNamespace::Klass) * %template(VectKlass) std::vector; - * - * Warning: heavy macro usage in this file. Use swig -E to get a sane view on the real file contents! * ----------------------------------------------------------------------------- */ -// Warning: Use the typemaps here in the expectation that the macros they are in will change name. - - %include // MACRO for use within the std::vector class body %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CSINTERFACE, CONST_REFERENCE, CTYPE...) -%typemap(csinterfaces) std::vector< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable\n , global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n"; -%typemap(cscode) std::vector< CTYPE > %{ - public $csclassname(global::System.Collections.ICollection c) : this() { +%typemap(csinterfaces) std::vector< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable, global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n"; +%proxycode %{ + public $csclassname(global::System.Collections.IEnumerable c) : this() { + if (c == null) + throw new global::System.ArgumentNullException("c"); + foreach ($typemap(cstype, CTYPE) element in c) { + this.Add(element); + } + } + + public $csclassname(global::System.Collections.Generic.IEnumerable<$typemap(cstype, CTYPE)> c) : this() { if (c == null) throw new global::System.ArgumentNullException("c"); foreach ($typemap(cstype, CTYPE) element in c) { @@ -62,7 +65,7 @@ set { if (value < size()) throw new global::System.ArgumentOutOfRangeException("Capacity"); - reserve((uint)value); + reserve(($typemap(cstype, size_t))value); } } @@ -106,6 +109,12 @@ array.SetValue(getitemcopy(index+i), arrayIndex+i); } + public $typemap(cstype, CTYPE)[] ToArray() { + $typemap(cstype, CTYPE)[] array = new $typemap(cstype, CTYPE)[this.Count]; + this.CopyTo(array); + return array; + } + global::System.Collections.Generic.IEnumerator<$typemap(cstype, CTYPE)> global::System.Collections.Generic.IEnumerable<$typemap(cstype, CTYPE)>.GetEnumerator() { return new $csclassnameEnumerator(this); } @@ -187,8 +196,13 @@ public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef CTYPE value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef CONST_REFERENCE const_reference; + %rename(Clear) clear; void clear(); %rename(Add) push_back; @@ -198,8 +212,10 @@ void reserve(size_type n); %newobject GetRange(int index, int count); %newobject Repeat(CTYPE const& value, int count); + vector(); vector(const vector &other); + %extend { vector(int capacity) throw (std::out_of_range) { std::vector< CTYPE >* pv = 0; @@ -324,7 +340,7 @@ std::vector< CTYPE >::iterator it = std::find($self->begin(), $self->end(), value); if (it != $self->end()) { $self->erase(it); - return true; + return true; } return false; } @@ -335,7 +351,7 @@ %define SWIG_STD_VECTOR_ENHANCED(CTYPE...) namespace std { template<> class vector< CTYPE > { - SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, %arg(CTYPE const&), %arg(CTYPE)) + SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, const value_type&, %arg(CTYPE)) SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CTYPE) }; } @@ -368,11 +384,11 @@ namespace std { // primary (unspecialized) class template for std::vector // does not require operator== to be defined template class vector { - SWIG_STD_VECTOR_MINIMUM_INTERNAL(IEnumerable, T const&, T) + SWIG_STD_VECTOR_MINIMUM_INTERNAL(IEnumerable, const value_type&, T) }; // specialization for pointers template class vector { - SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, T *const&, T *) + SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, const value_type&, T *) SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(T *) }; // bool is specialized in the C++ standard - const_reference in particular @@ -398,4 +414,5 @@ SWIG_STD_VECTOR_ENHANCED(unsigned long long) SWIG_STD_VECTOR_ENHANCED(float) SWIG_STD_VECTOR_ENHANCED(double) SWIG_STD_VECTOR_ENHANCED(std::string) // also requires a %include +SWIG_STD_VECTOR_ENHANCED(std::wstring) // also requires a %include diff --git a/Lib/csharp/std_wstring.i b/Lib/csharp/std_wstring.i index 09bdaaaa2..162b90e80 100644 --- a/Lib/csharp/std_wstring.i +++ b/Lib/csharp/std_wstring.i @@ -23,7 +23,10 @@ class wstring; // wstring %typemap(ctype, out="void *") wstring "wchar_t *" -%typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]") wstring "string" +%typemap(imtype, + inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" + ) wstring "string" %typemap(cstype) wstring "string" %typemap(csdirectorin) wstring "$iminput" %typemap(csdirectorout) wstring "$cscall" @@ -60,7 +63,10 @@ class wstring; // const wstring & %typemap(ctype, out="void *") const wstring & "wchar_t *" -%typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]") const wstring & "string" +%typemap(imtype, + inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" + ) const wstring & "string" %typemap(cstype) const wstring & "string" %typemap(csdirectorin) const wstring & "$iminput" diff --git a/Lib/csharp/stl.i b/Lib/csharp/stl.i index 9d2e91eee..04f86014f 100644 --- a/Lib/csharp/stl.i +++ b/Lib/csharp/stl.i @@ -1,7 +1,5 @@ /* ----------------------------------------------------------------------------- * stl.i - * - * Initial STL definition. extended as needed in each language * ----------------------------------------------------------------------------- */ %include diff --git a/Lib/csharp/wchar.i b/Lib/csharp/wchar.i index 9361edf6f..79fb5a8cf 100644 --- a/Lib/csharp/wchar.i +++ b/Lib/csharp/wchar.i @@ -20,6 +20,7 @@ static SWIG_CSharpWStringHelperCallback SWIG_csharp_wstring_callback = NULL; %pragma(csharp) imclasscode=%{ protected class SWIGWStringHelper { + [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)] public delegate string SWIGWStringDelegate(global::System.IntPtr message); static SWIGWStringDelegate wstringDelegate = new SWIGWStringDelegate(CreateWString); diff --git a/Lib/d/boost_shared_ptr.i b/Lib/d/boost_shared_ptr.i index 5c171555e..4a220a589 100644 --- a/Lib/d/boost_shared_ptr.i +++ b/Lib/d/boost_shared_ptr.i @@ -1,7 +1,9 @@ %include +// Language specific macro implementing all the customisations for handling the smart pointer %define SWIG_SHARED_PTR_TYPEMAPS(CONST, TYPE...) +// %naturalvar is as documented for member variables %naturalvar TYPE; %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; @@ -10,6 +12,7 @@ //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ((*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\"))) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" +// Typemap customisations... // plain value %typemap(in, canthrow=1) CONST TYPE ($&1_type argp = 0) %{ @@ -22,6 +25,18 @@ %typemap(out) CONST TYPE %{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} +%typemap(directorin) CONST TYPE +%{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype((const $1_ltype &)$1)); %} + +%typemap(directorout) CONST TYPE +%{ if (!$input) { + SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "Attempt to dereference null $1_type"); + return $null; + } + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input; + $result = *smartarg->get(); +%} + // plain pointer %typemap(in, canthrow=1) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ smartarg = (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input; @@ -30,6 +45,13 @@ $result = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0; %} +%typemap(directorin) CONST TYPE * +%{ $input = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; %} + +%typemap(directorout) CONST TYPE * %{ +#error "typemaps for $1_type not available" +%} + // plain reference %typemap(in, canthrow=1) CONST TYPE & %{ $1 = ($1_ltype)(((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input) ? ((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input)->get() : 0); @@ -40,6 +62,13 @@ %typemap(out, fragment="SWIG_null_deleter") CONST TYPE & %{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner); %} +%typemap(directorin) CONST TYPE & +%{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (&$1 SWIG_NO_NULL_DELETER_0); %} + +%typemap(directorout) CONST TYPE & %{ +#error "typemaps for $1_type not available" +%} + // plain pointer by reference %typemap(in) TYPE *CONST& ($*1_ltype temp = 0) %{ temp = (TYPE *)(((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input) ? ((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input)->get() : 0); @@ -47,18 +76,42 @@ %typemap(out, fragment="SWIG_null_deleter") TYPE *CONST& %{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner); %} +%typemap(directorin) TYPE *CONST& +%{ $input = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; %} + +%typemap(directorout) TYPE *CONST& %{ +#error "typemaps for $1_type not available" +%} + // shared_ptr by value %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > %{ if ($input) $1 = *($&1_ltype)$input; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > %{ $result = $1 ? new $1_ltype($1) : 0; %} +%typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > +%{ $input = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > +%{ if ($input) { + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)$input; + $result = *smartarg; + } +%} + // shared_ptr by reference %typemap(in, canthrow=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & ($*1_ltype tempnull) %{ $1 = $input ? ($1_ltype)$input : &tempnull; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{ $result = *$1 ? new $*1_ltype(*$1) : 0; %} +%typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & +%{ $input = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{ +#error "typemaps for $1_type not available" +%} + // shared_ptr by pointer %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * ($*1_ltype tempnull) %{ $1 = $input ? ($1_ltype)$input : &tempnull; %} @@ -66,6 +119,13 @@ %{ $result = ($1 && *$1) ? new $*1_ltype(*($1_ltype)$1) : 0; if ($owner) delete $1; %} +%typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * +%{ $input = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{ +#error "typemaps for $1_type not available" +%} + // shared_ptr by pointer reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempnull, $*1_ltype temp = 0) %{ temp = $input ? *($1_ltype)&$input : &tempnull; @@ -73,6 +133,13 @@ %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{ *($1_ltype)&$result = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %} +%typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& +%{ $input = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{ +#error "typemaps for $1_type not available" +%} + // various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug %typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{ #error "typemaps for $1_type not available" @@ -96,9 +163,22 @@ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(dtype, TYPE)" %typemap(din) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(dtype, TYPE).swigGetCPtr($dinput)" + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(dtype, TYPE).swigGetCPtr($dinput)" + +%typemap(ddirectorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > "$typemap(dtype, TYPE).swigGetCPtr($dcall)" + +%typemap(ddirectorin) CONST TYPE, + CONST TYPE *, + CONST TYPE &, + TYPE *CONST& "($winput is null) ? null : new $typemap(dtype, TYPE)($winput, true)" + +%typemap(ddirectorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "($winput is null) ? null : new $typemap(dtype, TYPE)($winput, true)" + %typemap(dout, excode=SWIGEXCODE) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > { void* cPtr = $imcall; @@ -141,8 +221,7 @@ return ret; } -// For shared pointers, both the derived and the base class have to »own« their -// pointer; otherwise the reference count is not decreased properly on destruction. +// Proxy classes (base classes, ie, not derived classes) %typemap(dbody) SWIGTYPE %{ private void* swigCPtr; private bool swigCMemOwn; @@ -157,6 +236,7 @@ public static void* swigGetCPtr(typeof(this) obj) { } %} +// Derived proxy classes %typemap(dbody_derived) SWIGTYPE %{ private void* swigCPtr; private bool swigCMemOwn; @@ -197,5 +277,17 @@ public static void* swigGetCPtr(typeof(this) obj) { } } +// Typecheck typemaps +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") + TYPE CONST, + TYPE CONST &, + TYPE CONST *, + TYPE *CONST&, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "" + %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/d/dclassgen.swg b/Lib/d/dclassgen.swg index 68910b412..84fa03a0b 100644 --- a/Lib/d/dclassgen.swg +++ b/Lib/d/dclassgen.swg @@ -33,7 +33,7 @@ // We do not use »override« attribute for generated dispose() methods to stay // somewhat compatible to Phobos and older Tango versions where Object.dispose() // does not exist. -%typemap(ddispose, methodname="dispose", methodmodifiers="public") SWIGTYPE { +%typemap(ddispose, methodname="dispose", methodmodifiers="public", parameters="") SWIGTYPE { synchronized(this) { if (swigCPtr !is null) { if (swigCMemOwn) { @@ -45,7 +45,7 @@ } } -%typemap(ddispose_derived, methodname="dispose", methodmodifiers="public") SWIGTYPE { +%typemap(ddispose_derived, methodname="dispose", methodmodifiers="public", parameters="") SWIGTYPE { synchronized(this) { if (swigCPtr !is null) { if (swigCMemOwn) { diff --git a/Lib/d/ddirectives.swg b/Lib/d/ddirectives.swg index 6972a0c18..145cf01f0 100644 --- a/Lib/d/ddirectives.swg +++ b/Lib/d/ddirectives.swg @@ -8,3 +8,4 @@ #define %dconstvalue(value) %feature("d:constvalue",value) #define %dmethodmodifiers %feature("d:methodmodifiers") #define %dnothrowexception %feature("except") +#define %proxycode %insert("proxycode") diff --git a/Lib/d/director.swg b/Lib/d/director.swg index a7d9c7688..02da0e0ac 100644 --- a/Lib/d/director.swg +++ b/Lib/d/director.swg @@ -40,6 +40,10 @@ namespace Swig { public: DirectorPureVirtualException(const char *msg) : DirectorException(std::string("Attempted to invoke pure virtual method ") + msg) { } + + static void raise(const char *msg) { + throw DirectorPureVirtualException(msg); + } }; } diff --git a/Lib/d/dmemberfunctionpointers.swg b/Lib/d/dmemberfunctionpointers.swg index c63eca23e..a07d0a5d8 100644 --- a/Lib/d/dmemberfunctionpointers.swg +++ b/Lib/d/dmemberfunctionpointers.swg @@ -43,6 +43,8 @@ return ret; } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } /* * Helper functions to pack/unpack arbitrary binary data (member function diff --git a/Lib/d/dprimitives.swg b/Lib/d/dprimitives.swg index 445437957..eaee816d3 100644 --- a/Lib/d/dprimitives.swg +++ b/Lib/d/dprimitives.swg @@ -20,7 +20,7 @@ /* * The SWIG_D_PRIMITIVE macro is used to define the typemaps for the primitive * types, because are more or less the same for all of them. The few special - * cases are handeled below. + * cases are handled below. */ %define SWIG_D_PRIMITIVE(TYPE, DTYPE) %typemap(ctype) TYPE, const TYPE & "TYPE" diff --git a/Lib/d/dswigtype.swg b/Lib/d/dswigtype.swg index f91d6dfe6..f0d604b6f 100644 --- a/Lib/d/dswigtype.swg +++ b/Lib/d/dswigtype.swg @@ -162,7 +162,7 @@ return ret; } -// Treat references to arrays like like references to a single element. +// Treat references to arrays like references to a single element. %apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } @@ -182,3 +182,16 @@ $*dclassname ret = (cPtr is null) ? null : new $*dclassname(cPtr, $owner);$excode return ret; } +%typemap(directorin) SWIGTYPE *const& + "$input = (void *) $1;" +%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE *const& +%{ static $*1_ltype swig_temp; + swig_temp = ($*1_ltype)$input; + $result = &swig_temp; %} +%typemap(ddirectorin, + nativepointer="cast($dtype)$winput" +) SWIGTYPE *const& "($winput is null) ? null : new $*dclassname($winput, false)" +%typemap(ddirectorout, + nativepointer="cast(void*)$dcall" +) SWIGTYPE *const& "$*dclassname.swigGetCPtr($dcall)" + diff --git a/Lib/d/std_except.i b/Lib/d/std_except.i index 2b557e5fc..fbfd6c337 100644 --- a/Lib/d/std_except.i +++ b/Lib/d/std_except.i @@ -7,6 +7,7 @@ * ----------------------------------------------------------------------------- */ %{ +#include #include %} @@ -16,6 +17,7 @@ namespace std struct exception {}; } +%typemap(throws, canthrow=1) std::bad_cast "SWIG_DSetPendingException(SWIG_DException, $1.what());\n return $null;" %typemap(throws, canthrow=1) std::bad_exception "SWIG_DSetPendingException(SWIG_DException, $1.what());\n return $null;" %typemap(throws, canthrow=1) std::domain_error "SWIG_DSetPendingException(SWIG_DException, $1.what());\n return $null;" %typemap(throws, canthrow=1) std::exception "SWIG_DSetPendingException(SWIG_DException, $1.what());\n return $null;" diff --git a/Lib/d/std_map.i b/Lib/d/std_map.i index 0e8574b8a..c5e03d06d 100644 --- a/Lib/d/std_map.i +++ b/Lib/d/std_map.i @@ -16,44 +16,47 @@ #include %} -// exported class - namespace std { - template class map { - // add typemaps here - public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef K key_type; - typedef T mapped_type; - map(); - map(const map &); + template > class map { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; - unsigned int size() const; - bool empty() const; - void clear(); - %extend { - const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); - if (i != self->end()) - return i->second; - else - throw std::out_of_range("key not found"); - } - void set(const K& key, const T& x) { - (*self)[key] = x; - } - void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); - if (i != self->end()) - self->erase(i); - else - throw std::out_of_range("key not found"); - } - bool has_key(const K& key) { - std::map::iterator i = self->find(key); - return i != self->end(); - } + map(); + map(const map& other); + + unsigned int size() const; + bool empty() const; + void clear(); + %extend { + const T& get(const K& key) throw (std::out_of_range) { + std::map< K, T, C >::iterator i = self->find(key); + if (i != self->end()) + return i->second; + else + throw std::out_of_range("key not found"); } - }; + void set(const K& key, const T& x) { + (*self)[key] = x; + } + void del(const K& key) throw (std::out_of_range) { + std::map< K, T, C >::iterator i = self->find(key); + if (i != self->end()) + self->erase(i); + else + throw std::out_of_range("key not found"); + } + bool has_key(const K& key) { + std::map< K, T, C >::iterator i = self->find(key); + return i != self->end(); + } + } + }; } diff --git a/Lib/d/std_pair.i b/Lib/d/std_pair.i index 0712ad762..732347db5 100644 --- a/Lib/d/std_pair.i +++ b/Lib/d/std_pair.i @@ -18,12 +18,14 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; pair(); - pair(T t, U u); - pair(const pair& p); + pair(T first, U second); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/d/std_vector.i b/Lib/d/std_vector.i index 50942f289..fb8f7d2e0 100644 --- a/Lib/d/std_vector.i +++ b/Lib/d/std_vector.i @@ -24,7 +24,7 @@ %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CONST_REFERENCE, CTYPE...) #if (SWIG_D_VERSION == 1) %typemap(dimports) std::vector< CTYPE > "static import tango.core.Exception;" -%typemap(dcode) std::vector< CTYPE > %{ +%proxycode %{ public this($typemap(dtype, CTYPE)[] values) { this(); append(values); @@ -104,15 +104,22 @@ public void capacity(size_t value) { public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef CTYPE value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef CONST_REFERENCE const_reference; + void clear(); void push_back(CTYPE const& x); size_type size() const; size_type capacity() const; void reserve(size_type n) throw (std::length_error); + vector(); vector(const vector &other); + %extend { vector(size_type capacity) throw (std::length_error) { std::vector< CTYPE >* pv = 0; @@ -128,7 +135,7 @@ public void capacity(size_t value) { return $self->capacity() - $self->size(); } - CONST_REFERENCE remove() throw (std::out_of_range) { + const_reference remove() throw (std::out_of_range) { if ($self->empty()) { throw std::out_of_range("Tried to remove last element from empty vector."); } @@ -138,7 +145,7 @@ public void capacity(size_t value) { return value; } - CONST_REFERENCE remove(size_type index) throw (std::out_of_range) { + const_reference remove(size_type index) throw (std::out_of_range) { if (index >= $self->size()) { throw std::out_of_range("Tried to remove element with invalid index."); } @@ -153,7 +160,7 @@ public void capacity(size_t value) { // Wrappers for setting/getting items with the possibly thrown exception // specified (important for SWIG wrapper generation). %extend { - CONST_REFERENCE getElement(size_type index) throw (std::out_of_range) { + const_reference getElement(size_type index) throw (std::out_of_range) { if ((index < 0) || ($self->size() <= index)) { throw std::out_of_range("Tried to get value of element with invalid index."); } @@ -185,7 +192,7 @@ static import std.exception; static import std.range; static import std.traits; %} -%typemap(dcode) std::vector< CTYPE > %{ +%proxycode %{ alias size_t KeyType; alias $typemap(dtype, CTYPE) ValueType; @@ -442,8 +449,13 @@ int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef CTYPE value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef CONST_REFERENCE const_reference; + bool empty() const; void clear(); void push_back(CTYPE const& x); @@ -451,8 +463,10 @@ int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) size_type size() const; size_type capacity() const; void reserve(size_type n) throw (std::length_error); + vector(); vector(const vector &other); + %extend { vector(size_type capacity) throw (std::length_error) { std::vector< CTYPE >* pv = 0; @@ -464,7 +478,7 @@ int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) return pv; } - CONST_REFERENCE remove() throw (std::out_of_range) { + const_reference remove() throw (std::out_of_range) { if ($self->empty()) { throw std::out_of_range("Tried to remove last element from empty vector."); } @@ -474,7 +488,7 @@ int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) return value; } - CONST_REFERENCE remove(size_type index) throw (std::out_of_range) { + const_reference remove(size_type index) throw (std::out_of_range) { if (index >= $self->size()) { throw std::out_of_range("Tried to remove element with invalid index."); } @@ -506,7 +520,7 @@ int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) // Wrappers for setting/getting items with the possibly thrown exception // specified (important for SWIG wrapper generation). %extend { - CONST_REFERENCE getElement(size_type index) throw (std::out_of_range) { + const_reference getElement(size_type index) throw (std::out_of_range) { if ((index < 0) || ($self->size() <= index)) { throw std::out_of_range("Tried to get value of element with invalid index."); } @@ -544,7 +558,7 @@ int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) %define SWIG_STD_VECTOR_ENHANCED(CTYPE...) namespace std { template<> class vector { - SWIG_STD_VECTOR_MINIMUM_INTERNAL(%arg(CTYPE const&), %arg(CTYPE)) + SWIG_STD_VECTOR_MINIMUM_INTERNAL(const value_type&, %arg(CTYPE)) SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CTYPE) }; } @@ -559,11 +573,11 @@ namespace std { // primary (unspecialized) class template for std::vector // does not require operator== to be defined template class vector { - SWIG_STD_VECTOR_MINIMUM_INTERNAL(T const&, T) + SWIG_STD_VECTOR_MINIMUM_INTERNAL(const value_type&, T) }; // specializations for pointers template class vector { - SWIG_STD_VECTOR_MINIMUM_INTERNAL(T *const&, T *) + SWIG_STD_VECTOR_MINIMUM_INTERNAL(const value_type&, T *) SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(T *) }; // bool is a bit different in the C++ standard - const_reference in particular diff --git a/Lib/d/stl.i b/Lib/d/stl.i index 9d2e91eee..04f86014f 100644 --- a/Lib/d/stl.i +++ b/Lib/d/stl.i @@ -1,7 +1,5 @@ /* ----------------------------------------------------------------------------- * stl.i - * - * Initial STL definition. extended as needed in each language * ----------------------------------------------------------------------------- */ %include diff --git a/Lib/exception.i b/Lib/exception.i index 437eee6f0..ee9ce9bc6 100644 --- a/Lib/exception.i +++ b/Lib/exception.i @@ -12,10 +12,10 @@ %insert("runtime") "swigerrors.swg" -#ifdef SWIGPHP +#ifdef SWIGPHP7 %{ #include "zend_exceptions.h" -#define SWIG_exception(code, msg) zend_throw_exception(NULL, (char*)msg, code TSRMLS_CC) +#define SWIG_exception(code, msg) do { zend_throw_exception(NULL, (char*)msg, code); goto thrown; } while (0) %} #endif @@ -127,33 +127,48 @@ SWIGINTERN void SWIG_JavaException(JNIEnv *jenv, int code, const char *msg) { #ifdef SWIGOCAML %{ -#define OCAML_MSG_BUF_LEN 1024 -SWIGINTERN void SWIG_exception_(int code, const char *msg) { - char msg_buf[OCAML_MSG_BUF_LEN]; - sprintf( msg_buf, "Exception(%d): %s\n", code, msg ); - failwith( msg_buf ); +SWIGINTERN void SWIG_OCamlException(int code, const char *msg) { + CAMLparam0(); + + SWIG_OCamlExceptionCodes exception_code = SWIG_OCamlUnknownError; + switch (code) { + case SWIG_DivisionByZero: + exception_code = SWIG_OCamlArithmeticException; + break; + case SWIG_IndexError: + exception_code = SWIG_OCamlIndexOutOfBoundsException; + break; + case SWIG_IOError: + case SWIG_SystemError: + exception_code = SWIG_OCamlSystemException; + break; + case SWIG_MemoryError: + exception_code = SWIG_OCamlOutOfMemoryError; + break; + case SWIG_OverflowError: + exception_code = SWIG_OCamlOverflowException; + break; + case SWIG_RuntimeError: + exception_code = SWIG_OCamlRuntimeException; + break; + case SWIG_SyntaxError: + case SWIG_TypeError: + case SWIG_ValueError: + exception_code = SWIG_OCamlIllegalArgumentException; + break; + case SWIG_UnknownError: + default: + exception_code = SWIG_OCamlUnknownError; + break; + } + SWIG_OCamlThrowException(exception_code, msg); + CAMLreturn0; } -#define SWIG_exception(a,b) SWIG_exception_((a),(b)) +#define SWIG_exception(code, msg) SWIG_OCamlException(code, msg) %} #endif -#ifdef SWIGCHICKEN -%{ -SWIGINTERN void SWIG_exception_(int code, const char *msg) { - C_word *a; - C_word scmmsg; - C_word list; - - a = C_alloc (C_SIZEOF_STRING (strlen (msg)) + C_SIZEOF_LIST(2)); - scmmsg = C_string2 (&a, (char *) msg); - list = C_list(&a, 2, C_fix(code), scmmsg); - SWIG_ThrowException(list); -} -#define SWIG_exception(a,b) SWIG_exception_((a),(b)) -%} -#endif - #ifdef SWIGCSHARP %{ SWIGINTERN void SWIG_CSharpException(int code, const char *msg) { @@ -258,6 +273,7 @@ SWIGINTERN void SWIG_DThrowException(int code, const char *msg) { } */ %{ +#include #include %} %define SWIG_CATCH_STDEXCEPT @@ -274,6 +290,8 @@ SWIGINTERN void SWIG_DThrowException(int code, const char *msg) { SWIG_exception(SWIG_IndexError, e.what() ); } catch (std::runtime_error& e) { SWIG_exception(SWIG_RuntimeError, e.what() ); + } catch (std::bad_cast& e) { + SWIG_exception(SWIG_TypeError, e.what() ); } catch (std::exception& e) { SWIG_exception(SWIG_SystemError, e.what() ); } diff --git a/Lib/gcj/cni.i b/Lib/gcj/cni.i deleted file mode 100644 index fcc56687a..000000000 --- a/Lib/gcj/cni.i +++ /dev/null @@ -1,39 +0,0 @@ -%{ -#include -%} - -%include - -extern void JvInitClass (jclass cls); - -extern jstring JvAllocString (jsize sz); - -extern jstring JvNewString (const jchar *chars, jsize len); - -extern jstring JvNewStringLatin1 (const char *bytes, jsize len); - -extern jstring JvNewStringLatin1 (const char *bytes); - -extern jchar* JvGetStringChars (jstring str); - -extern jsize JvGetStringUTFLength (jstring string); - -extern jsize JvGetStringUTFRegion (jstring str, jsize start, jsize len, char *buf); - -extern jstring JvNewStringUTF (const char *bytes); - -extern void *JvMalloc (jsize size); - -extern void JvFree (void *ptr); - -extern jint JvCreateJavaVM (JvVMInitArgs* vm_args); - -extern java::lang::Thread* JvAttachCurrentThread (jstring name, java::lang::ThreadGroup* group); - -extern java::lang::Thread* JvAttachCurrentThreadAsDaemon (jstring name, java::lang::ThreadGroup* group); - -extern jint JvDetachCurrentThread (void); - - -%include - diff --git a/Lib/gcj/cni.swg b/Lib/gcj/cni.swg deleted file mode 100644 index 4bd07df06..000000000 --- a/Lib/gcj/cni.swg +++ /dev/null @@ -1,14 +0,0 @@ -/* ----------------------------------------------------------------------------- - * cni.swg - * ----------------------------------------------------------------------------- */ - -#ifdef SWIG - -#define __attribute__(...) -%ignore class$; -#pragma SWIG nowarn=313,402 - -%nodefaultdtor; - -#endif - diff --git a/Lib/gcj/javaprims.i b/Lib/gcj/javaprims.i deleted file mode 100644 index 12c92a793..000000000 --- a/Lib/gcj/javaprims.i +++ /dev/null @@ -1,422 +0,0 @@ -%include - -typedef int8_t jbyte; -typedef int16_t jshort; -typedef int32_t jint; -typedef int64_t jlong; -typedef float jfloat; -typedef double jdouble; -typedef jint jsize; -typedef int8_t jboolean; - -extern "Java" -{ - namespace java - { - namespace io - { - class BufferedInputStream; - class BufferedOutputStream; - class BufferedReader; - class BufferedWriter; - class ByteArrayInputStream; - class ByteArrayOutputStream; - class CharArrayReader; - class CharArrayWriter; - class CharConversionException; - class DataInput; - class DataInputStream; - class DataOutput; - class DataOutputStream; - class EOFException; - class Externalizable; - class File; - class FileDescriptor; - class FileFilter; - class FileInputStream; - class FileNotFoundException; - class FileOutputStream; - class FilePermission; - class FileReader; - class FileWriter; - class FilenameFilter; - class FilterInputStream; - class FilterOutputStream; - class FilterReader; - class FilterWriter; - class IOException; - class InputStream; - class InputStreamReader; - class InterfaceComparator; - class InterruptedIOException; - class InvalidClassException; - class InvalidObjectException; - class LineNumberInputStream; - class LineNumberReader; - class MemberComparator; - class NotActiveException; - class NotSerializableException; - class ObjectInput; - class ObjectInputStream; - class ObjectInputStream$GetField; - class ObjectInputValidation; - class ObjectOutput; - class ObjectOutputStream; - class ObjectOutputStream$PutField; - class ObjectStreamClass; - class ObjectStreamConstants; - class ObjectStreamException; - class ObjectStreamField; - class OptionalDataException; - class OutputStream; - class OutputStreamWriter; - class PipedInputStream; - class PipedOutputStream; - class PipedReader; - class PipedWriter; - class PrintStream; - class PrintWriter; - class PushbackInputStream; - class PushbackReader; - class RandomAccessFile; - class Reader; - class SequenceInputStream; - class Serializable; - class SerializablePermission; - class StreamCorruptedException; - class StreamTokenizer; - class StringBufferInputStream; - class StringReader; - class StringWriter; - class SyncFailedException; - class UTFDataFormatException; - class UnsupportedEncodingException; - class VMObjectStreamClass; - class ValidatorAndPriority; - class WriteAbortedException; - class Writer; - } - - namespace lang - { - class AbstractMethodError; - class ArithmeticException; - class ArrayIndexOutOfBoundsException; - class ArrayStoreException; - class AssertionError; - class Boolean; - class Byte; - class CharSequence; - class Character; - class Character$Subset; - class Character$UnicodeBlock; - class Class; - class ClassCastException; - class ClassCircularityError; - class ClassFormatError; - class ClassLoader; - class ClassNotFoundException; - class CloneNotSupportedException; - class Cloneable; - class Comparable; - class Compiler; - class ConcreteProcess; - class Double; - class Error; - class Exception; - class ExceptionInInitializerError; - class Float; - class IllegalAccessError; - class IllegalAccessException; - class IllegalArgumentException; - class IllegalMonitorStateException; - class IllegalStateException; - class IllegalThreadStateException; - class IncompatibleClassChangeError; - class IndexOutOfBoundsException; - class InheritableThreadLocal; - class InstantiationError; - class InstantiationException; - class Integer; - class InternalError; - class InterruptedException; - class LinkageError; - class Long; - class Math; - class NegativeArraySizeException; - class NoClassDefFoundError; - class NoSuchFieldError; - class NoSuchFieldException; - class NoSuchMethodError; - class NoSuchMethodException; - class NullPointerException; - class Number; - class NumberFormatException; - class Object; - class OutOfMemoryError; - class Package; - class Process; - class Runnable; - class Runtime; - class RuntimeException; - class RuntimePermission; - class SecurityContext; - class SecurityException; - class SecurityManager; - class Short; - class StackOverflowError; - class StackTraceElement; - class StrictMath; - class String; - class String$CaseInsensitiveComparator; - class StringBuffer; - class StringIndexOutOfBoundsException; - class System; - class Thread; - class ThreadDeath; - class ThreadGroup; - class ThreadLocal; - class Throwable; - class UnknownError; - class UnsatisfiedLinkError; - class UnsupportedClassVersionError; - class UnsupportedOperationException; - class VMClassLoader; - class VMSecurityManager; - class VMThrowable; - class VerifyError; - class VirtualMachineError; - class Void; - namespace ref - { - class PhantomReference; - class Reference; - class ReferenceQueue; - class SoftReference; - class WeakReference; - } - - namespace reflect - { - class AccessibleObject; - class Array; - class Constructor; - class Field; - class InvocationHandler; - class InvocationTargetException; - class Member; - class Method; - class Modifier; - class Proxy; - class Proxy$ClassFactory; - class Proxy$ProxyData; - class Proxy$ProxySignature; - class Proxy$ProxyType; - class ReflectPermission; - class UndeclaredThrowableException; - } - } - - namespace util - { - class AbstractCollection; - class AbstractList; - class AbstractMap; - class AbstractMap$BasicMapEntry; - class AbstractSequentialList; - class AbstractSet; - class ArrayList; - class Arrays; - class Arrays$ArrayList; - class BitSet; - class Calendar; - class Collection; - class Collections; - class Collections$CopiesList; - class Collections$EmptyList; - class Collections$EmptyMap; - class Collections$EmptySet; - class Collections$ReverseComparator; - class Collections$SingletonList; - class Collections$SingletonMap; - class Collections$SingletonSet; - class Collections$SynchronizedCollection; - class Collections$SynchronizedIterator; - class Collections$SynchronizedList; - class Collections$SynchronizedListIterator; - class Collections$SynchronizedMap; - class Collections$SynchronizedMapEntry; - class Collections$SynchronizedRandomAccessList; - class Collections$SynchronizedSet; - class Collections$SynchronizedSortedMap; - class Collections$SynchronizedSortedSet; - class Collections$UnmodifiableCollection; - class Collections$UnmodifiableEntrySet; - class Collections$UnmodifiableIterator; - class Collections$UnmodifiableList; - class Collections$UnmodifiableListIterator; - class Collections$UnmodifiableMap; - class Collections$UnmodifiableRandomAccessList; - class Collections$UnmodifiableSet; - class Collections$UnmodifiableSortedMap; - class Collections$UnmodifiableSortedSet; - class Comparator; - class ConcurrentModificationException; - class Currency; - class Date; - class Dictionary; - class EmptyStackException; - class Enumeration; - class EventListener; - class EventListenerProxy; - class EventObject; - class GregorianCalendar; - class HashMap; - class HashMap$HashEntry; - class HashMap$HashIterator; - class HashSet; - class Hashtable; - class Hashtable$Enumerator; - class Hashtable$HashEntry; - class Hashtable$HashIterator; - class IdentityHashMap; - class IdentityHashMap$IdentityEntry; - class IdentityHashMap$IdentityIterator; - class Iterator; - class LinkedHashMap; - class LinkedHashMap$LinkedHashEntry; - class LinkedHashSet; - class LinkedList; - class LinkedList$Entry; - class LinkedList$LinkedListItr; - class List; - class ListIterator; - class ListResourceBundle; - class Locale; - class Map; - class Map$Entry; - class Map$Map; - class MissingResourceException; - class MyResources; - class NoSuchElementException; - class Observable; - class Observer; - class Properties; - class PropertyPermission; - class PropertyPermissionCollection; - class PropertyResourceBundle; - class Random; - class RandomAccess; - class RandomAccessSubList; - class ResourceBundle; - class Set; - class SimpleTimeZone; - class SortedMap; - class SortedSet; - class Stack; - class StringTokenizer; - class SubList; - class TimeZone; - class Timer; - class Timer$Scheduler; - class Timer$TaskQueue; - class TimerTask; - class TooManyListenersException; - class TreeMap; - class TreeMap$Node; - class TreeMap$SubMap; - class TreeMap$TreeIterator; - class TreeSet; - class Vector; - class WeakHashMap; - class WeakHashMap$WeakBucket; - class WeakHashMap$WeakEntry; - class WeakHashMap$WeakEntrySet; - namespace jar - { - class Attributes; - class Attributes$Name; - class JarEntry; - class JarException; - class JarFile; - class JarFile$JarEnumeration; - class JarInputStream; - class JarOutputStream; - class Manifest; - } - - namespace logging - { - class ConsoleHandler; - class ErrorManager; - class FileHandler; - class Filter; - class Formatter; - class Handler; - class Level; - class LogManager; - class LogRecord; - class Logger; - class LoggingPermission; - class MemoryHandler; - class SimpleFormatter; - class SocketHandler; - class StreamHandler; - class XMLFormatter; - } - - namespace prefs - { - class AbstractPreferences; - class BackingStoreException; - class InvalidPreferencesFormatException; - class NodeChangeEvent; - class NodeChangeListener; - class PreferenceChangeEvent; - class PreferenceChangeListener; - class Preferences; - class PreferencesFactory; - } - - namespace regex - { - class Matcher; - class Pattern; - class PatternSyntaxException; - } - - namespace zip - { - class Adler32; - class CRC32; - class CheckedInputStream; - class CheckedOutputStream; - class Checksum; - class DataFormatException; - class Deflater; - class DeflaterOutputStream; - class GZIPInputStream; - class GZIPOutputStream; - class Inflater; - class InflaterInputStream; - class ZipConstants; - class ZipEntry; - class ZipException; - class ZipFile; - class ZipFile$PartialInputStream; - class ZipFile$ZipEntryEnumeration; - class ZipInputStream; - class ZipOutputStream; - } - } - } -} - -typedef class java::lang::Object* jobject; -typedef class java::lang::Class* jclass; -typedef class java::lang::Throwable* jthrowable; -typedef class java::lang::String* jstring; - - -%include - diff --git a/Lib/go/director.swg b/Lib/go/director.swg new file mode 100644 index 000000000..103ba22a3 --- /dev/null +++ b/Lib/go/director.swg @@ -0,0 +1,80 @@ +/* ----------------------------------------------------------------------------- + * director.swg + * + * This file contains support for director classes so that Go proxy + * methods can be called from C++. + * ----------------------------------------------------------------------------- */ + +#include +#include + +namespace Swig { + + class DirectorException : public std::exception { + }; +} + +/* Handle memory management for directors. */ + +namespace { + struct GCItem { + virtual ~GCItem() {} + }; + + struct GCItem_var { + GCItem_var(GCItem *item = 0) : _item(item) { + } + + GCItem_var& operator=(GCItem *item) { + GCItem *tmp = _item; + _item = item; + delete tmp; + return *this; + } + + ~GCItem_var() { + delete _item; + } + + GCItem* operator->() { + return _item; + } + + private: + GCItem *_item; + }; + + template + struct GCItem_T : GCItem { + GCItem_T(Type *ptr) : _ptr(ptr) { + } + + virtual ~GCItem_T() { + delete _ptr; + } + + private: + Type *_ptr; + }; +} + +class Swig_memory { +public: + template + void swig_acquire_pointer(Type* vptr) { + if (vptr) { + swig_owner[vptr] = new GCItem_T(vptr); + } + } +private: + typedef std::map swig_ownership_map; + swig_ownership_map swig_owner; +}; + +template +static void swig_acquire_pointer(Swig_memory** pmem, Type* ptr) { + if (!pmem) { + *pmem = new Swig_memory; + } + (*pmem)->swig_acquire_pointer(ptr); +} diff --git a/Lib/go/go.swg b/Lib/go/go.swg index 53b653f7c..c225ed9ad 100644 --- a/Lib/go/go.swg +++ b/Lib/go/go.swg @@ -341,8 +341,6 @@ %typemap(directorout) SWIGTYPE * %{ $result = *($&1_ltype)&$input; %} -%apply SWIGTYPE * { SWIGTYPE *const } - /* Pointer references. */ %typemap(gotype) SWIGTYPE *const& @@ -382,6 +380,11 @@ %typemap(directorout) SWIGTYPE & %{ *($&1_ltype)&$result = $input; %} +%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE *const& +%{ static $*1_ltype swig_temp; + swig_temp = *($1_ltype)&$input; + $result = &swig_temp; %} + %typemap(gotype) SWIGTYPE && %{$gotypename%} @@ -692,6 +695,10 @@ SWIGTYPE (CLASS::*) "" +%apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } + /* Go keywords. */ %include diff --git a/Lib/go/goruntime.swg b/Lib/go/goruntime.swg index dc6193d04..269a4eefd 100644 --- a/Lib/go/goruntime.swg +++ b/Lib/go/goruntime.swg @@ -346,75 +346,6 @@ type _swig_fnptr *byte type _swig_memberptr *byte %} -/* Handle memory management for directors. */ - -%insert(director) %{ -#include - -namespace { - struct GCItem { - virtual ~GCItem() {} - }; - - struct GCItem_var { - GCItem_var(GCItem *item = 0) : _item(item) { - } - - GCItem_var& operator=(GCItem *item) { - GCItem *tmp = _item; - _item = item; - delete tmp; - return *this; - } - - ~GCItem_var() { - delete _item; - } - - GCItem* operator->() { - return _item; - } - - private: - GCItem *_item; - }; - - template - struct GCItem_T : GCItem { - GCItem_T(Type *ptr) : _ptr(ptr) { - } - - virtual ~GCItem_T() { - delete _ptr; - } - - private: - Type *_ptr; - }; -} - -class Swig_memory { -public: - template - void swig_acquire_pointer(Type* vptr) { - if (vptr) { - swig_owner[vptr] = new GCItem_T(vptr); - } - } -private: - typedef std::map swig_ownership_map; - swig_ownership_map swig_owner; -}; - -template -static void swig_acquire_pointer(Swig_memory** pmem, Type* ptr) { - if (!pmem) { - *pmem = new Swig_memory; - } - (*pmem)->swig_acquire_pointer(ptr); -} -%} - /* For directors we need C++ to track a Go pointer. Since we can't pass a Go pointer into C++, we use a map to track the pointers on the Go side. */ diff --git a/Lib/go/std_except.i b/Lib/go/std_except.i index 789a335f7..4f021a126 100644 --- a/Lib/go/std_except.i +++ b/Lib/go/std_except.i @@ -7,6 +7,7 @@ * ----------------------------------------------------------------------------- */ %{ +#include #include %} @@ -16,6 +17,7 @@ namespace std struct exception {}; } +%typemap(throws) std::bad_cast %{_swig_gopanic($1.what());%} %typemap(throws) std::bad_exception %{_swig_gopanic($1.what());%} %typemap(throws) std::domain_error %{_swig_gopanic($1.what());%} %typemap(throws) std::exception %{_swig_gopanic($1.what());%} diff --git a/Lib/go/std_list.i b/Lib/go/std_list.i index e0262331e..ff6f70013 100644 --- a/Lib/go/std_list.i +++ b/Lib/go/std_list.i @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * std_vector.i + * std_list.i * ----------------------------------------------------------------------------- */ %{ @@ -9,7 +9,7 @@ namespace std { - template > + template class list { public: typedef size_t size_type; @@ -19,9 +19,10 @@ namespace std { typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; - typedef Alloc allocator_type; list(); + list(const list& other); + size_type size() const; bool empty() const; %rename(isEmpty) empty; diff --git a/Lib/go/std_map.i b/Lib/go/std_map.i index 84b0c74ff..773b6d0c3 100644 --- a/Lib/go/std_map.i +++ b/Lib/go/std_map.i @@ -20,22 +20,28 @@ namespace std { - template class map { + template > class map { // add typemaps here public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -45,14 +51,14 @@ namespace std { (*self)[key] = x; } void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } } diff --git a/Lib/go/std_pair.i b/Lib/go/std_pair.i index fe45ee676..732347db5 100644 --- a/Lib/go/std_pair.i +++ b/Lib/go/std_pair.i @@ -18,12 +18,14 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/go/std_vector.i b/Lib/go/std_vector.i index 29bcd1391..679c70759 100644 --- a/Lib/go/std_vector.i +++ b/Lib/go/std_vector.i @@ -12,10 +12,17 @@ namespace std { template class vector { public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef const value_type& const_reference; + vector(); vector(size_type n); + vector(const vector& other); + size_type size() const; size_type capacity() const; void reserve(size_type n); @@ -46,10 +53,17 @@ namespace std { template<> class vector { public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef bool value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef bool const_reference; + vector(); vector(size_type n); + vector(const vector& other); + size_type size() const; size_type capacity() const; void reserve(size_type n); diff --git a/Lib/go/stl.i b/Lib/go/stl.i index 38aba67b8..04f86014f 100644 --- a/Lib/go/stl.i +++ b/Lib/go/stl.i @@ -7,3 +7,4 @@ %include %include %include + diff --git a/Lib/guile/guile_scm.swg b/Lib/guile/guile_scm.swg index dfd5da271..16dc8aa92 100644 --- a/Lib/guile/guile_scm.swg +++ b/Lib/guile/guile_scm.swg @@ -8,6 +8,7 @@ #define SWIGGUILE_SCM %runtime "swigrun.swg" // Common C API type-checking code +%runtime "swigerrors.swg" // SWIG errors %runtime "guile_scm_run.swg" %include @@ -26,10 +27,10 @@ else { \ if (!gswig_list_p) { \ gswig_list_p = 1; \ - gswig_result = scm_listify(gswig_result, object, SCM_UNDEFINED); \ + gswig_result = scm_list_n(gswig_result, object, SCM_UNDEFINED); \ } \ else \ - gswig_result = scm_append(scm_listify(gswig_result, scm_listify(object, SCM_UNDEFINED), SCM_UNDEFINED)); \ + gswig_result = scm_append(scm_list_n(gswig_result, scm_list_n(object, SCM_UNDEFINED), SCM_UNDEFINED)); \ } %} diff --git a/Lib/guile/guile_scm_run.swg b/Lib/guile/guile_scm_run.swg index 94cf4d101..86e5c3be0 100644 --- a/Lib/guile/guile_scm_run.swg +++ b/Lib/guile/guile_scm_run.swg @@ -24,6 +24,8 @@ scm_module_variable (SCM module, SCM sym) return scm_sym2var (sym, scm_module_lookup_closure (module), SCM_BOOL_F); } +#define scm_to_utf8_string scm_to_locale_string +#define scm_from_utf8_string scm_from_locale_string #endif #if SCM_MAJOR_VERSION >= 2 @@ -40,10 +42,6 @@ typedef struct swig_guile_clientdata { SCM goops_class; } swig_guile_clientdata; -#if SCM_MAJOR_VERSION <= 2 -#define scm_to_utf8_string scm_to_locale_string -#define scm_from_utf8_string scm_from_locale_string -#endif #define SWIG_scm2str(s) \ SWIG_Guile_scm2newstr(s, NULL) #define SWIG_str02scm(str) \ @@ -101,6 +99,7 @@ SWIG_Guile_scm2newstr(SCM str, size_t *len) { static int swig_initialized = 0; static scm_t_bits swig_tag = 0; static scm_t_bits swig_collectable_tag = 0; +static scm_t_bits swig_finalized_tag = 0; static scm_t_bits swig_destroyed_tag = 0; static scm_t_bits swig_member_function_tag = 0; static SCM swig_make_func = SCM_EOL; @@ -165,7 +164,19 @@ SWIG_Guile_PointerType(SCM object) } else scm_wrong_type_arg("SWIG-Guile-PointerType", 1, object); } - + +SWIGINTERN int +SWIG_Guile_IsValidSmob(SCM smob) +{ + /* We do not accept smobs representing destroyed pointers, but we have to + allow finalized smobs because Guile >= 2.0.12 sets all smob instances + to the 'finalized' type before calling their 'free' function. This change + was introduced to Guile in commit 8dff3af087c6eaa83ae0d72aa8b22aef5c65d65d */ + return SCM_SMOB_PREDICATE(swig_tag, smob) + || SCM_SMOB_PREDICATE(swig_collectable_tag, smob) + || SCM_SMOB_PREDICATE(swig_finalized_tag, smob); +} + SWIGINTERN int SWIG_Guile_ConvertPtr(SCM s, void **result, swig_type_info *type, int flags) { @@ -175,9 +186,13 @@ SWIG_Guile_ConvertPtr(SCM s, void **result, swig_type_info *type, int flags) if (SCM_NULLP(smob)) { *result = NULL; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; +#if SCM_MAJOR_VERSION >= 2 + } else if (SCM_POINTER_P(s)) { + *result = SCM_POINTER_VALUE(s); return SWIG_OK; - } else if (SCM_SMOB_PREDICATE(swig_tag, smob) || SCM_SMOB_PREDICATE(swig_collectable_tag, smob)) { - /* we do not accept smobs representing destroyed pointers */ +#endif /* if SCM_MAJOR_VERSION >= 2 */ + } else if (SWIG_Guile_IsValidSmob(smob)) { from = (swig_type_info *) SCM_CELL_WORD_2(smob); if (!from) return SWIG_ERROR; if (type) { @@ -236,7 +251,7 @@ SWIG_Guile_MarkPointerNoncollectable(SCM s) { SCM smob = SWIG_Guile_GetSmob(s); if (!SCM_NULLP(smob)) { - if (SCM_SMOB_PREDICATE(swig_tag, smob) || SCM_SMOB_PREDICATE(swig_collectable_tag, smob)) { + if (SWIG_Guile_IsValidSmob(smob)) { SCM_SET_CELL_TYPE(smob, swig_tag); } else scm_wrong_type_arg(NULL, 0, s); @@ -249,7 +264,7 @@ SWIG_Guile_MarkPointerDestroyed(SCM s) { SCM smob = SWIG_Guile_GetSmob(s); if (!SCM_NULLP(smob)) { - if (SCM_SMOB_PREDICATE(swig_tag, smob) || SCM_SMOB_PREDICATE(swig_collectable_tag, smob)) { + if (SWIG_Guile_IsValidSmob(smob)) { SCM_SET_CELL_TYPE(smob, swig_destroyed_tag); } else scm_wrong_type_arg(NULL, 0, s); @@ -416,6 +431,8 @@ SWIG_Guile_Init () scm_set_smob_print(swig_collectable_tag, print_collectable_swig); scm_set_smob_equalp(swig_collectable_tag, equalp_swig); scm_set_smob_free(swig_collectable_tag, free_swig); + /* For Guile >= 2.0.12. See libguile/smob.c:clear_smobnum */ + swig_finalized_tag = swig_collectable_tag & ~0xff00; } if (ensure_smob_tag(swig_module, &swig_destroyed_tag, "destroyed-swig-pointer", "destroyed-swig-pointer-tag")) { diff --git a/Lib/guile/guilemain.i b/Lib/guile/guilemain.i index 925b81fee..809154e99 100644 --- a/Lib/guile/guilemain.i +++ b/Lib/guile/guilemain.i @@ -12,11 +12,6 @@ extern "C" { #endif -/* Debugger interface (don't change the order of the following lines) */ -#define GDB_TYPE SCM -#include -GDB_INTERFACE; - static void inner_main(void *closure, int argc, char **argv) { diff --git a/Lib/guile/std_common.i b/Lib/guile/std_common.i index 18c7db089..5899c5548 100644 --- a/Lib/guile/std_common.i +++ b/Lib/guile/std_common.i @@ -14,7 +14,8 @@ %{ #include -inline std::string SWIG_scm2string(SCM x) { +SWIGINTERNINLINE +std::string SWIG_scm2string(SCM x) { char* temp; temp = SWIG_scm2str(x); std::string s(temp); diff --git a/Lib/guile/std_except.i b/Lib/guile/std_except.i index 61bf481a3..6c30a319f 100644 --- a/Lib/guile/std_except.i +++ b/Lib/guile/std_except.i @@ -1,6 +1,7 @@ // TODO: STL exception handling // Note that the generic std_except.i file did not work %{ +#include #include %} diff --git a/Lib/guile/std_map.i b/Lib/guile/std_map.i index 489acc187..f84e78bc3 100644 --- a/Lib/guile/std_map.i +++ b/Lib/guile/std_map.i @@ -40,12 +40,12 @@ namespace std { - template class map { - %typemap(in) map { + template > class map { + %typemap(in) map< K, T, C > { if (scm_is_null($input)) { - $1 = std::map< K, T >(); + $1 = std::map< K, T, C >(); } else if (scm_is_pair($input)) { - $1 = std::map< K, T >(); + $1 = std::map< K, T, C >(); SCM alist = $input; while (!scm_is_null(alist)) { K* k; @@ -72,13 +72,13 @@ namespace std { SWIG_MustGetPtr($input,$&1_descriptor,$argnum, 0)); } } - %typemap(in) const map& (std::map temp), - const map* (std::map temp) { + %typemap(in) const map< K, T, C >& (std::map< K, T, C > temp), + const map< K, T, C >* (std::map< K, T, C > temp) { if (scm_is_null($input)) { - temp = std::map< K, T >(); + temp = std::map< K, T, C >(); $1 = &temp; } else if (scm_is_pair($input)) { - temp = std::map< K, T >(); + temp = std::map< K, T, C >(); $1 = &temp; SCM alist = $input; while (!scm_is_null(alist)) { @@ -105,9 +105,9 @@ namespace std { $1 = ($1_ltype) SWIG_MustGetPtr($input,$1_descriptor,$argnum, 0); } } - %typemap(out) map { + %typemap(out) map< K, T, C > { SCM alist = SCM_EOL; - for (std::map< K, T >::reverse_iterator i=$i.rbegin(); i!=$i.rend(); ++i) { + for (std::map< K, T, C >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { K* key = new K(i->first); T* val = new T(i->second); SCM k = SWIG_NewPointerObj(key,$descriptor(K *), 1); @@ -117,7 +117,7 @@ namespace std { } $result = alist; } - %typecheck(SWIG_TYPECHECK_MAP) map { + %typecheck(SWIG_TYPECHECK_MAP) map< K, T, C > { /* native sequence? */ if (scm_is_null($input)) { /* an empty sequence can be of any type */ @@ -153,7 +153,7 @@ namespace std { } } else { /* wrapped map? */ - std::map< K, T >* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $&1_descriptor, 0) == 0) $1 = 1; @@ -161,8 +161,8 @@ namespace std { $1 = 0; } } - %typecheck(SWIG_TYPECHECK_MAP) const map&, - const map* { + %typecheck(SWIG_TYPECHECK_MAP) const map< K, T, C >&, + const map< K, T, C >* { /* native sequence? */ if (scm_is_null($input)) { /* an empty sequence can be of any type */ @@ -198,7 +198,7 @@ namespace std { } } else { /* wrapped map? */ - std::map< K, T >* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $1_descriptor, 0) == 0) $1 = 1; @@ -218,15 +218,21 @@ namespace std { typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map< K, T> &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { const T& __getitem__(const K& key) throw (std::out_of_range) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -236,19 +242,19 @@ namespace std { (*self)[key] = x; } void __delitem__(const K& key) throw (std::out_of_range) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } SCM keys() { SCM result = SCM_EOL; - for (std::map< K, T >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { + for (std::map< K, T, C >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { K* key = new K(i->first); SCM k = SWIG_NewPointerObj(key,$descriptor(K *), 1); result = scm_cons(k,result); @@ -263,12 +269,12 @@ namespace std { %define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) - template class map { - %typemap(in) map { + template class map< K, T, C > { + %typemap(in) map< K, T, C > { if (scm_is_null($input)) { - $1 = std::map< K, T >(); + $1 = std::map< K, T, C >(); } else if (scm_is_pair($input)) { - $1 = std::map< K, T >(); + $1 = std::map< K, T, C >(); SCM alist = $input; while (!scm_is_null(alist)) { T* x; @@ -280,7 +286,7 @@ namespace std { val = SCM_CDR(entry); if (!CHECK(key)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); if (SWIG_ConvertPtr(val,(void**) &x, $descriptor(T *), 0) != 0) { if (!scm_is_pair(val)) @@ -296,13 +302,13 @@ namespace std { SWIG_MustGetPtr($input,$&1_descriptor,$argnum, 0)); } } - %typemap(in) const map& (std::map temp), - const map* (std::map temp) { + %typemap(in) const map< K, T, C >& (std::map< K, T, C > temp), + const map< K, T, C >* (std::map< K, T, C > temp) { if (scm_is_null($input)) { - temp = std::map< K, T >(); + temp = std::map< K, T, C >(); $1 = &temp; } else if (scm_is_pair($input)) { - temp = std::map< K, T >(); + temp = std::map< K, T, C >(); $1 = &temp; SCM alist = $input; while (!scm_is_null(alist)) { @@ -315,7 +321,7 @@ namespace std { val = SCM_CDR(entry); if (!CHECK(key)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); if (SWIG_ConvertPtr(val,(void**) &x, $descriptor(T *), 0) != 0) { if (!scm_is_pair(val)) @@ -330,9 +336,9 @@ namespace std { $1 = ($1_ltype) SWIG_MustGetPtr($input,$1_descriptor,$argnum, 0); } } - %typemap(out) map { + %typemap(out) map< K, T, C > { SCM alist = SCM_EOL; - for (std::map< K, T >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { + for (std::map< K, T, C >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { T* val = new T(i->second); SCM k = CONVERT_TO(i->first); SCM x = SWIG_NewPointerObj(val,$descriptor(T *), 1); @@ -341,7 +347,7 @@ namespace std { } $result = alist; } - %typecheck(SWIG_TYPECHECK_MAP) map { + %typecheck(SWIG_TYPECHECK_MAP) map< K, T, C > { // native sequence? if (scm_is_null($input)) { /* an empty sequence can be of any type */ @@ -375,7 +381,7 @@ namespace std { } } else { // wrapped map? - std::map< K, T >* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $&1_descriptor, 0) == 0) $1 = 1; @@ -383,8 +389,8 @@ namespace std { $1 = 0; } } - %typecheck(SWIG_TYPECHECK_MAP) const map&, - const map* { + %typecheck(SWIG_TYPECHECK_MAP) const map< K, T, C >&, + const map< K, T, C >* { // native sequence? if (scm_is_null($input)) { /* an empty sequence can be of any type */ @@ -418,7 +424,7 @@ namespace std { } } else { // wrapped map? - std::map< K, T >* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $1_descriptor, 0) == 0) $1 = 1; @@ -434,15 +440,25 @@ namespace std { %rename("delete!") __delitem__; %rename("has-key?") has_key; public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map< K, T > &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { T& __getitem__(K key) throw (std::out_of_range) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -452,19 +468,19 @@ namespace std { (*self)[key] = x; } void __delitem__(K key) throw (std::out_of_range) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(K key) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } SCM keys() { SCM result = SCM_EOL; - for (std::map< K, T >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { + for (std::map< K, T, C >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { SCM k = CONVERT_TO(i->first); result = scm_cons(k,result); } @@ -475,12 +491,12 @@ namespace std { %enddef %define specialize_std_map_on_value(T,CHECK,CONVERT_FROM,CONVERT_TO) - template class map { - %typemap(in) map { + template class map< K, T, C > { + %typemap(in) map< K, T, C > { if (scm_is_null($input)) { - $1 = std::map< K, T >(); + $1 = std::map< K, T, C >(); } else if (scm_is_pair($input)) { - $1 = std::map< K, T >(); + $1 = std::map< K, T, C >(); SCM alist = $input; while (!scm_is_null(alist)) { K* k; @@ -497,7 +513,7 @@ namespace std { val = SCM_CAR(val); if (!CHECK(val)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); } (($1_type &)$1)[*k] = CONVERT_FROM(val); alist = SCM_CDR(alist); @@ -507,13 +523,13 @@ namespace std { SWIG_MustGetPtr($input,$&1_descriptor,$argnum, 0)); } } - %typemap(in) const map& (std::map temp), - const map* (std::map temp) { + %typemap(in) const map< K, T, C >& (std::map< K, T, C > temp), + const map< K, T, C >* (std::map< K, T, C > temp) { if (scm_is_null($input)) { - temp = std::map< K, T >(); + temp = std::map< K, T, C >(); $1 = &temp; } else if (scm_is_pair($input)) { - temp = std::map< K, T >(); + temp = std::map< K, T, C >(); $1 = &temp; SCM alist = $input; while (!scm_is_null(alist)) { @@ -531,7 +547,7 @@ namespace std { val = SCM_CAR(val); if (!CHECK(val)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); } temp[*k] = CONVERT_FROM(val); alist = SCM_CDR(alist); @@ -540,9 +556,9 @@ namespace std { $1 = ($1_ltype) SWIG_MustGetPtr($input,$1_descriptor,$argnum, 0); } } - %typemap(out) map { + %typemap(out) map< K, T, C > { SCM alist = SCM_EOL; - for (std::map< K, T >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { + for (std::map< K, T, C >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { K* key = new K(i->first); SCM k = SWIG_NewPointerObj(key,$descriptor(K *), 1); SCM x = CONVERT_TO(i->second); @@ -551,7 +567,7 @@ namespace std { } $result = alist; } - %typecheck(SWIG_TYPECHECK_MAP) map { + %typecheck(SWIG_TYPECHECK_MAP) map< K, T, C > { // native sequence? if (scm_is_null($input)) { /* an empty sequence can be of any type */ @@ -583,7 +599,7 @@ namespace std { } } else { // wrapped map? - std::map< K, T >* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $&1_descriptor, 0) == 0) $1 = 1; @@ -591,8 +607,8 @@ namespace std { $1 = 0; } } - %typecheck(SWIG_TYPECHECK_MAP) const map&, - const map* { + %typecheck(SWIG_TYPECHECK_MAP) const map< K, T, C >&, + const map< K, T, C >* { // native sequence? if (scm_is_null($input)) { /* an empty sequence can be of any type */ @@ -624,7 +640,7 @@ namespace std { } } else { // wrapped map? - std::map< K, T >* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $1_descriptor, 0) == 0) $1 = 1; @@ -640,15 +656,25 @@ namespace std { %rename("delete!") __delitem__; %rename("has-key?") has_key; public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map< K, T > &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { T __getitem__(const K& key) throw (std::out_of_range) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -658,19 +684,19 @@ namespace std { (*self)[key] = x; } void __delitem__(const K& key) throw (std::out_of_range) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } SCM keys() { SCM result = SCM_EOL; - for (std::map< K, T >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { + for (std::map< K, T, C >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { K* key = new K(i->first); SCM k = SWIG_NewPointerObj(key,$descriptor(K *), 1); result = scm_cons(k,result); @@ -683,12 +709,12 @@ namespace std { %define specialize_std_map_on_both(K,CHECK_K,CONVERT_K_FROM,CONVERT_K_TO, T,CHECK_T,CONVERT_T_FROM,CONVERT_T_TO) - template<> class map { - %typemap(in) map { + template<> class map< K, T, C > { + %typemap(in) map< K, T, C > { if (scm_is_null($input)) { - $1 = std::map< K, T >(); + $1 = std::map< K, T, C >(); } else if (scm_is_pair($input)) { - $1 = std::map< K, T >(); + $1 = std::map< K, T, C >(); SCM alist = $input; while (!scm_is_null(alist)) { SCM entry, key, val; @@ -699,14 +725,14 @@ namespace std { val = SCM_CDR(entry); if (!CHECK_K(key)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); if (!CHECK_T(val)) { if (!scm_is_pair(val)) SWIG_exception(SWIG_TypeError,"alist expected"); val = SCM_CAR(val); if (!CHECK_T(val)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); } (($1_type &)$1)[CONVERT_K_FROM(key)] = CONVERT_T_FROM(val); @@ -717,13 +743,13 @@ namespace std { SWIG_MustGetPtr($input,$&1_descriptor,$argnum, 0)); } } - %typemap(in) const map& (std::map temp), - const map* (std::map temp) { + %typemap(in) const map< K, T, C >& (std::map< K, T, C > temp), + const map< K, T, C >* (std::map< K, T, C > temp) { if (scm_is_null($input)) { - temp = std::map< K, T >(); + temp = std::map< K, T, C >(); $1 = &temp; } else if (scm_is_pair($input)) { - temp = std::map< K, T >(); + temp = std::map< K, T, C >(); $1 = &temp; SCM alist = $input; while (!scm_is_null(alist)) { @@ -735,14 +761,14 @@ namespace std { val = SCM_CDR(entry); if (!CHECK_K(key)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); if (!CHECK_T(val)) { if (!scm_is_pair(val)) SWIG_exception(SWIG_TypeError,"alist expected"); val = SCM_CAR(val); if (!CHECK_T(val)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); } temp[CONVERT_K_FROM(key)] = CONVERT_T_FROM(val); alist = SCM_CDR(alist); @@ -751,9 +777,9 @@ namespace std { $1 = ($1_ltype) SWIG_MustGetPtr($input,$1_descriptor,$argnum, 0); } } - %typemap(out) map { + %typemap(out) map< K, T, C > { SCM alist = SCM_EOL; - for (std::map< K, T >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { + for (std::map< K, T, C >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { SCM k = CONVERT_K_TO(i->first); SCM x = CONVERT_T_TO(i->second); SCM entry = scm_cons(k,x); @@ -761,7 +787,7 @@ namespace std { } $result = alist; } - %typecheck(SWIG_TYPECHECK_MAP) map { + %typecheck(SWIG_TYPECHECK_MAP) map< K, T, C > { // native sequence? if (scm_is_null($input)) { /* an empty sequence can be of any type */ @@ -792,7 +818,7 @@ namespace std { } } else { // wrapped map? - std::map< K, T >* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $&1_descriptor, 0) == 0) $1 = 1; @@ -800,8 +826,8 @@ namespace std { $1 = 0; } } - %typecheck(SWIG_TYPECHECK_MAP) const map&, - const map* { + %typecheck(SWIG_TYPECHECK_MAP) const map< K, T, C >&, + const map< K, T, C >* { // native sequence? if (scm_is_null($input)) { /* an empty sequence can be of any type */ @@ -832,7 +858,7 @@ namespace std { } } else { // wrapped map? - std::map< K, T >* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $1_descriptor, 0) == 0) $1 = 1; @@ -848,15 +874,25 @@ namespace std { %rename("delete!") __delitem__; %rename("has-key?") has_key; public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map< K, T> &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { T __getitem__(K key) throw (std::out_of_range) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -866,19 +902,19 @@ namespace std { (*self)[key] = x; } void __delitem__(K key) throw (std::out_of_range) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(K key) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } SCM keys() { SCM result = SCM_EOL; - for (std::map< K, T >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { + for (std::map< K, T, C >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { SCM k = CONVERT_K_TO(i->first); result = scm_cons(k,result); } diff --git a/Lib/guile/std_pair.i b/Lib/guile/std_pair.i index 92dec5fae..050d4880a 100644 --- a/Lib/guile/std_pair.i +++ b/Lib/guile/std_pair.i @@ -113,11 +113,15 @@ namespace std { $1 = 0; } } + + typedef T first_type; + typedef U second_type; + pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; @@ -217,9 +221,9 @@ namespace std { } pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; @@ -317,9 +321,9 @@ namespace std { } pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; @@ -408,9 +412,9 @@ namespace std { } pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/guile/std_vector.i b/Lib/guile/std_vector.i index d7a7140c6..42bad849d 100644 --- a/Lib/guile/std_vector.i +++ b/Lib/guile/std_vector.i @@ -187,9 +187,18 @@ namespace std { } } public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + vector(unsigned int size = 0); vector(unsigned int size, const T& value); - vector(const vector&); + vector(const vector& other); + %rename(length) size; unsigned int size() const; %rename("empty?") empty; @@ -351,9 +360,18 @@ namespace std { } } public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + vector(unsigned int size = 0); vector(unsigned int size, const T& value); - vector(const vector&); + vector(const vector& other); + %rename(length) size; unsigned int size() const; %rename("empty?") empty; diff --git a/Lib/guile/stl.i b/Lib/guile/stl.i index 9d2e91eee..04f86014f 100644 --- a/Lib/guile/stl.i +++ b/Lib/guile/stl.i @@ -1,7 +1,5 @@ /* ----------------------------------------------------------------------------- * stl.i - * - * Initial STL definition. extended as needed in each language * ----------------------------------------------------------------------------- */ %include diff --git a/Lib/guile/typemaps.i b/Lib/guile/typemaps.i index a01e73f64..cfccced88 100644 --- a/Lib/guile/typemaps.i +++ b/Lib/guile/typemaps.i @@ -69,13 +69,13 @@ %typemap(throws) SWIGTYPE { $<ype temp = new $ltype($1); scm_throw(scm_from_locale_symbol((char *) "swig-exception"), - scm_listify(SWIG_NewPointerObj(temp, $&descriptor, 1), + scm_list_n(SWIG_NewPointerObj(temp, $&descriptor, 1), SCM_UNDEFINED)); } %typemap(throws) SWIGTYPE & { scm_throw(scm_from_locale_symbol((char *) "swig-exception"), - scm_listify(SWIG_NewPointerObj(&$1, $descriptor, 1), + scm_list_n(SWIG_NewPointerObj(&$1, $descriptor, 1), SCM_UNDEFINED)); } @@ -87,13 +87,13 @@ %typemap(throws) SWIGTYPE * { scm_throw(scm_from_locale_symbol((char *) "swig-exception"), - scm_listify(SWIG_NewPointerObj($1, $descriptor, 1), + scm_list_n(SWIG_NewPointerObj($1, $descriptor, 1), SCM_UNDEFINED)); } %typemap(throws) SWIGTYPE [] { scm_throw(scm_from_locale_symbol((char *) "swig-exception"), - scm_listify(SWIG_NewPointerObj($1, $descriptor, 1), + scm_list_n(SWIG_NewPointerObj($1, $descriptor, 1), SCM_UNDEFINED)); } @@ -176,7 +176,7 @@ %typemap(varout) enum SWIGTYPE { $result = scm_from_long((int)$1); } %typemap(throws) enum SWIGTYPE { scm_throw(scm_from_locale_symbol((char *) "swig-exception"), - scm_listify(scm_from_long((int)$1), SCM_UNDEFINED)); + scm_list_n(scm_from_long((int)$1), SCM_UNDEFINED)); } /* The SIMPLE_MAP_WITH_EXPR macro below defines the whole set of @@ -225,7 +225,7 @@ %typemap(throws) C_NAME { C_NAME swig_c_value = $1; scm_throw(scm_from_locale_symbol((char *) "swig-exception"), - scm_listify(C_TO_SCM_EXPR, SCM_UNDEFINED)); + scm_list_n(C_TO_SCM_EXPR, SCM_UNDEFINED)); } %enddef @@ -269,7 +269,7 @@ /* Throw typemap */ %typemap(throws) C_NAME { scm_throw(scm_from_locale_symbol((char *) "swig-exception"), - scm_listify(C_TO_SCM($1), SCM_UNDEFINED)); + scm_list_n(C_TO_SCM($1), SCM_UNDEFINED)); } %enddef @@ -344,7 +344,7 @@ SIMPLE_MAP(unsigned long long, scm_to_ulong_long, scm_from_ulong_long, integer); %typemap(throws) char * { scm_throw(scm_from_locale_symbol((char *) "swig-exception"), - scm_listify(SWIG_str02scm($1), SCM_UNDEFINED)); + scm_list_n(SWIG_str02scm($1), SCM_UNDEFINED)); } /* Void */ @@ -444,15 +444,21 @@ typedef unsigned long SCM; $1 = scm_is_string($input) ? 1 : 0; } -%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] { +%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE [] { void *ptr; int res = SWIG_ConvertPtr($input, &ptr, $1_descriptor, 0); $1 = SWIG_CheckState(res); } +%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE &, SWIGTYPE && { + void *ptr; + int res = SWIG_ConvertPtr($input, &ptr, $1_descriptor, SWIG_POINTER_NO_NULL); + $1 = SWIG_CheckState(res); +} + %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { void *ptr; - int res = SWIG_ConvertPtr($input, &ptr, $&descriptor, 0); + int res = SWIG_ConvertPtr($input, &ptr, $&descriptor, SWIG_POINTER_NO_NULL); $1 = SWIG_CheckState(res); } @@ -468,5 +474,7 @@ typedef unsigned long SCM; /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } /* typemaps.i ends here */ diff --git a/Lib/intrusive_ptr.i b/Lib/intrusive_ptr.i index ceaeaf0bb..621a701f9 100644 --- a/Lib/intrusive_ptr.i +++ b/Lib/intrusive_ptr.i @@ -44,18 +44,16 @@ struct SWIG_null_deleter { %#define SWIG_NO_NULL_DELETER_1 } -// Workaround empty first macro argument bug -#define SWIGEMPTYHACK // Main user macro for defining intrusive_ptr typemaps for both const and non-const pointer types %define %intrusive_ptr(TYPE...) %feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > } -SWIG_INTRUSIVE_PTR_TYPEMAPS(SWIGEMPTYHACK, TYPE) +SWIG_INTRUSIVE_PTR_TYPEMAPS(, TYPE) SWIG_INTRUSIVE_PTR_TYPEMAPS(const, TYPE) %enddef %define %intrusive_ptr_no_wrap(TYPE...) %feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > } -SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(SWIGEMPTYHACK, TYPE) +SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(, TYPE) SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(const, TYPE) %enddef diff --git a/Lib/java/arrays_java.i b/Lib/java/arrays_java.i index 402f088d5..dd38438a3 100644 --- a/Lib/java/arrays_java.i +++ b/Lib/java/arrays_java.i @@ -337,7 +337,8 @@ JAVA_ARRAYS_TYPEMAPS(double, double, jdouble, Double, "[D") /* double[ANY] * /* Add some code to the proxy class of the array type for converting between type used in * JNI class (long[]) and type used in proxy class ( ARRAYSOFCLASSES[] ) */ -%typemap(javacode) ARRAYSOFCLASSES %{ +%extend ARRAYSOFCLASSES { +%proxycode %{ protected static long[] cArrayUnwrap($javaclassname[] arrayWrapper) { long[] cArray = new long[arrayWrapper.length]; for (int i=0; i **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(resultp, SWIG_intrusive_deleter< CONST TYPE >()); + *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(resultp, SWIG_intrusive_deleter< CONST TYPE >()); %} %typemap(in) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ // plain pointer smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input; - $1 = (TYPE *)(smartarg ? smartarg->get() : 0); + $1 = (TYPE *)(smartarg ? smartarg->get() : 0); %} %typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") CONST TYPE * %{ //plain pointer(out) #if ($owner) if ($1) { intrusive_ptr_add_ref($1); - *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1, SWIG_intrusive_deleter< CONST TYPE >()); + *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1, SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; } @@ -63,70 +63,70 @@ if(!$1) { SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null"); return $null; - } + } %} -%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") CONST TYPE & %{ +%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") CONST TYPE & %{ //plain reference(out) #if ($owner) if ($1) { intrusive_ptr_add_ref($1); - *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1, SWIG_intrusive_deleter< CONST TYPE >()); + *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1, SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; - } + } #else *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; #endif %} -%typemap(in) TYPE *CONST& ($*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ +%typemap(in) TYPE *CONST& ($*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ // plain pointer by reference temp = ($*1_ltype)((*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0); - $1 = &temp; + $1 = &temp; %} -%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") TYPE *CONST& %{ +%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") TYPE *CONST& %{ // plain pointer by reference(out) #if ($owner) if (*$1) { intrusive_ptr_add_ref(*$1); - *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1, SWIG_intrusive_deleter< CONST TYPE >()); + *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1, SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; - } + } #else *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_0); #endif %} -%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > ($&1_type argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ +%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > ($&1_type argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ // intrusive_ptr by value smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; if (smartarg) { - $1 = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true); + $1 = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true); } %} -%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > %{ +%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > %{ if ($1) { intrusive_ptr_add_ref(result.get()); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(result.get(), SWIG_intrusive_deleter< CONST TYPE >()); } else { - *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; + *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; } %} %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast ($&1_type smartarg) %{ // shared_ptr by value - smartarg = *($&1_ltype*)&$input; - if (smartarg) $1 = *smartarg; + smartarg = *($&1_ltype*)&$input; + if (smartarg) $1 = *smartarg; %} -%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ANY_TYPE_SWIGSharedPtrUpcast %{ - *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; +%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ANY_TYPE_SWIGSharedPtrUpcast %{ + *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; %} -%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & ($*1_ltype tempnull, $*1_ltype temp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ +%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & ($*1_ltype tempnull, $*1_ltype temp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ // intrusive_ptr by reference if ( $input ) { - smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; + smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; temp = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true); $1 = &temp; } else { @@ -140,21 +140,21 @@ $1 = *temp; } %} -%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & %{ +%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & %{ if (*$1) { intrusive_ptr_add_ref($1->get()); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1->get(), SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; } -%} +%} -%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * ($*1_ltype tempnull, $*1_ltype temp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ +%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * ($*1_ltype tempnull, $*1_ltype temp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ // intrusive_ptr by pointer if ( $input ) { - smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; + smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; temp = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true); - $1 = &temp; + $1 = &temp; } else { $1 = &tempnull; } @@ -163,17 +163,17 @@ delete $1; if ($self) $1 = new SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(*$input); %} -%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * %{ +%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * %{ if ($1 && *$1) { intrusive_ptr_add_ref($1->get()); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1->get(), SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; } - if ($owner) delete $1; + if ($owner) delete $1; %} -%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& (SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > temp, $*1_ltype tempp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ +%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& (SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > temp, $*1_ltype tempp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ // intrusive_ptr by pointer reference smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; if ($input) { @@ -185,14 +185,14 @@ %typemap(memberin) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& %{ if ($self) $1 = *$input; %} -%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& %{ +%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& %{ if (*$1 && **$1) { intrusive_ptr_add_ref((*$1)->get()); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >((*$1)->get(), SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; } -%} +%} // various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug %typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{ @@ -208,7 +208,7 @@ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > &, SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *, SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& "jlong" -%typemap (jtype) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >, +%typemap (jtype) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > &, SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *, @@ -264,7 +264,7 @@ // Base proxy classes %typemap(javabody) TYPE %{ private transient long swigCPtr; - private boolean swigCMemOwnBase; + private transient boolean swigCMemOwnBase; PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) { swigCMemOwnBase = cMemoryOwn; @@ -279,7 +279,7 @@ // Derived proxy classes %typemap(javabody_derived) TYPE %{ private transient long swigCPtr; - private boolean swigCMemOwnDerived; + private transient boolean swigCMemOwnDerived; PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) { super($imclassname.$javaclazznameSWIGSmartPtrUpcast(cPtr), true); @@ -341,7 +341,7 @@ return $null; } $1 = *argp; %} -%typemap(out) CONST TYPE +%typemap(out) CONST TYPE %{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} // plain pointer @@ -371,11 +371,11 @@ %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast ($&1_type smartarg) %{ // shared_ptr by value - smartarg = *($&1_ltype*)&$input; - if (smartarg) $1 = *smartarg; + smartarg = *($&1_ltype*)&$input; + if (smartarg) $1 = *smartarg; %} -%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ANY_TYPE_SWIGSharedPtrUpcast %{ - *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; +%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ANY_TYPE_SWIGSharedPtrUpcast %{ + *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; %} // various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug @@ -414,7 +414,7 @@ // Base proxy classes %typemap(javabody) TYPE %{ private transient long swigCPtr; - private boolean swigCMemOwnBase; + private transient boolean swigCMemOwnBase; PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) { swigCMemOwnBase = cMemoryOwn; @@ -429,7 +429,7 @@ // Derived proxy classes %typemap(javabody_derived) TYPE %{ private transient long swigCPtr; - private boolean swigCMemOwnDerived; + private transient boolean swigCMemOwnDerived; PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) { super($imclassname.$javaclazznameSWIGSmartPtrUpcast(cPtr), true); @@ -467,6 +467,17 @@ %typemap(jtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast "long" %typemap(jtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast "long" +// Typecheck typemaps +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") + TYPE CONST, + TYPE CONST &, + TYPE CONST *, + TYPE *CONST&, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "" %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/java/boost_shared_ptr.i b/Lib/java/boost_shared_ptr.i index 136570da5..325a6832d 100644 --- a/Lib/java/boost_shared_ptr.i +++ b/Lib/java/boost_shared_ptr.i @@ -14,7 +14,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor wrapper customisation -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -28,9 +28,22 @@ return $null; } $1 = *argp; %} -%typemap(out) CONST TYPE +%typemap(out) CONST TYPE %{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} +%typemap(directorin,descriptor="L$packagepath/$&javaclassname;") CONST TYPE +%{ $input = 0; + *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype((const $1_ltype &)$1)); %} + +%typemap(directorout) CONST TYPE +%{ if (!$input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type"); + return $null; + } + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input; + $result = *smartarg->get(); + %} + // plain pointer %typemap(in) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input; @@ -39,6 +52,16 @@ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0; %} +%typemap(directorin,descriptor="L$packagepath/$javaclassname;") CONST TYPE * +%{ $input = 0; + if ($1) { + *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ($1 SWIG_NO_NULL_DELETER_0); + } %} + +%typemap(directorout) CONST TYPE * %{ +#error "typemaps for $1_type not available" +%} + // plain reference %typemap(in) CONST TYPE & %{ $1 = ($1_ltype)((*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0); @@ -49,6 +72,14 @@ %typemap(out, fragment="SWIG_null_deleter") CONST TYPE & %{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner); %} +%typemap(directorin,descriptor="L$packagepath/$javaclassname;") CONST TYPE & +%{ $input = 0; + *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (&$1 SWIG_NO_NULL_DELETER_0); %} + +%typemap(directorout) CONST TYPE & %{ +#error "typemaps for $1_type not available" +%} + // plain pointer by reference %typemap(in) TYPE *CONST& ($*1_ltype temp = 0) %{ temp = (TYPE *)((*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0); @@ -56,18 +87,50 @@ %typemap(out, fragment="SWIG_null_deleter") TYPE *CONST& %{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner); %} +%typemap(directorin,descriptor="L$packagepath/$*javaclassname;") TYPE *CONST& +%{ $input = 0; + if ($1) { + *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ($1 SWIG_NO_NULL_DELETER_0); + } %} + +%typemap(directorout) TYPE *CONST& %{ +#error "typemaps for $1_type not available" +%} + // shared_ptr by value %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ($&1_type argp) -%{ argp = *($&1_ltype*)&$input; +%{ argp = *($&1_ltype*)&$input; if (argp) $1 = *argp; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > %{ *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; %} +%typemap(directorin,descriptor="L$packagepath/$typemap(jstype, TYPE);") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > +%{ $input = 0; + if ($1) { + *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1); + } %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > +%{ if ($input) { + $&1_type smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input; + $result = *smartarg; + } %} + // shared_ptr by reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & ($*1_ltype tempnull) %{ $1 = $input ? *($&1_ltype)&$input : &tempnull; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & -%{ *($&1_ltype)&$result = *$1 ? new $*1_ltype(*$1) : 0; %} +%{ *($&1_ltype)&$result = *$1 ? new $*1_ltype(*$1) : 0; %} + +%typemap(directorin,descriptor="L$packagepath/$typemap(jstype, TYPE);") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & +%{ $input = 0; + if ($1) { + *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1); + } %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{ +#error "typemaps for $1_type not available" +%} // shared_ptr by pointer %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * ($*1_ltype tempnull) @@ -76,12 +139,32 @@ %{ *($&1_ltype)&$result = ($1 && *$1) ? new $*1_ltype(*$1) : 0; if ($owner) delete $1; %} +%typemap(directorin,descriptor="L$packagepath/$typemap(jstype, TYPE);") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * +%{ $input = 0; + if ($1 && *$1) { + *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1); + } %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{ +#error "typemaps for $1_type not available" +%} + // shared_ptr by pointer reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempnull, $*1_ltype temp = 0) %{ temp = $input ? *($1_ltype)&$input : &tempnull; $1 = &temp; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& -%{ *($1_ltype)&$result = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %} +%{ *($1_ltype)&$result = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %} + +%typemap(directorin,descriptor="L$packagepath/$typemap(jstype, TYPE);") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& +%{ $input = 0; + if ($1 && *$1) { + *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1); + } %} + +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{ +#error "typemaps for $1_type not available" +%} // various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug %typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{ @@ -92,20 +175,20 @@ %} -%typemap (jni) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (jni) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "jlong" -%typemap (jtype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (jtype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "long" -%typemap (jstype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (jstype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(jstype, TYPE)" -%typemap(javain) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap(javain) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(jstype, TYPE).getCPtr($javainput)" @@ -143,6 +226,18 @@ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); } +%typemap(javadirectorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > "$typemap(jstype, TYPE).getCPtr($javacall)" + +%typemap(javadirectorin) CONST TYPE, + CONST TYPE *, + CONST TYPE &, + TYPE *CONST& "($jniinput == 0) ? null : new $typemap(jstype, TYPE)($jniinput, true)" + +%typemap(javadirectorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "($jniinput == 0) ? null : new $typemap(jstype, TYPE)($jniinput, true)" + // Base proxy classes %typemap(javabody) TYPE %{ private transient long swigCPtr; @@ -156,12 +251,16 @@ CPTR_VISIBILITY static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } + + CPTR_VISIBILITY void swigSetCMemOwn(boolean own) { + swigCMemOwn = own; + } %} // Derived proxy classes %typemap(javabody_derived) TYPE %{ private transient long swigCPtr; - private boolean swigCMemOwnDerived; + private transient boolean swigCMemOwnDerived; PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) { super($imclassname.$javaclazznameSWIGSmartPtrUpcast(cPtr), true); @@ -172,6 +271,11 @@ CPTR_VISIBILITY static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } + + CPTR_VISIBILITY void swigSetCMemOwn(boolean own) { + swigCMemOwnDerived = own; + super.swigSetCMemOwn(own); + } %} %typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") TYPE { @@ -195,6 +299,38 @@ super.delete(); } +%typemap(directordisconnect, methodname="swigDirectorDisconnect") TYPE %{ + protected void $methodname() { + swigSetCMemOwn(false); + $jnicall; + } +%} + +%typemap(directorowner_release, methodname="swigReleaseOwnership") TYPE %{ + public void $methodname() { + swigSetCMemOwn(false); + $jnicall; + } +%} + +%typemap(directorowner_take, methodname="swigTakeOwnership") TYPE %{ + public void $methodname() { + swigSetCMemOwn(true); + $jnicall; + } +%} + +// Typecheck typemaps +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") + TYPE CONST, + TYPE CONST &, + TYPE CONST *, + TYPE *CONST&, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "" %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/java/director.swg b/Lib/java/director.swg index 355e62d67..d3bd162ec 100644 --- a/Lib/java/director.swg +++ b/Lib/java/director.swg @@ -5,12 +5,52 @@ * methods can be called from C++. * ----------------------------------------------------------------------------- */ -#if defined(DEBUG_DIRECTOR_OWNED) || defined(DEBUG_DIRECTOR_EXCEPTION) +#if defined(DEBUG_DIRECTOR_OWNED) || defined(DEBUG_DIRECTOR_EXCEPTION) || defined(DEBUG_DIRECTOR_THREAD_NAME) #include #endif #include +#if defined(SWIG_JAVA_USE_THREAD_NAME) + +#if !defined(SWIG_JAVA_GET_THREAD_NAME) +namespace Swig { + SWIGINTERN int GetThreadName(char *name, size_t len); +} + +#if defined(__linux__) + +#include +SWIGINTERN int Swig::GetThreadName(char *name, size_t len) { + (void)len; +#if defined(PR_GET_NAME) + return prctl(PR_GET_NAME, (unsigned long)name, 0, 0, 0); +#else + (void)name; + return 1; +#endif +} + +#elif defined(__unix__) || defined(__APPLE__) + +#include +SWIGINTERN int Swig::GetThreadName(char *name, size_t len) { + return pthread_getname_np(pthread_self(), name, len); +} + +#else + +SWIGINTERN int Swig::GetThreadName(char *name, size_t len) { + (void)len; + (void)name; + return 1; +} +#endif + +#endif + +#endif + namespace Swig { /* Java object wrapper */ @@ -139,12 +179,27 @@ namespace Swig { void **jenv = (void **)&jenv_; #endif env_status = director_->swig_jvm_->GetEnv((void **)&jenv_, JNI_VERSION_1_2); + JavaVMAttachArgs args; + args.version = JNI_VERSION_1_2; + args.group = NULL; + args.name = NULL; +#if defined(SWIG_JAVA_USE_THREAD_NAME) + char thread_name[64]; // MAX_TASK_COMM_LEN=16 is hard-coded in the Linux kernel and MacOS has MAXTHREADNAMESIZE=64. + if (Swig::GetThreadName(thread_name, sizeof(thread_name)) == 0) { + args.name = thread_name; +#if defined(DEBUG_DIRECTOR_THREAD_NAME) + std::cout << "JNIEnvWrapper: thread name: " << thread_name << std::endl; + } else { + std::cout << "JNIEnvWrapper: Couldn't set Java thread name" << std::endl; +#endif + } +#endif #if defined(SWIG_JAVA_ATTACH_CURRENT_THREAD_AS_DAEMON) // Attach a daemon thread to the JVM. Useful when the JVM should not wait for // the thread to exit upon shutdown. Only for jdk-1.4 and later. - director_->swig_jvm_->AttachCurrentThreadAsDaemon(jenv, NULL); + director_->swig_jvm_->AttachCurrentThreadAsDaemon(jenv, &args); #else - director_->swig_jvm_->AttachCurrentThread(jenv, NULL); + director_->swig_jvm_->AttachCurrentThread(jenv, &args); #endif } ~JNIEnvWrapper() { @@ -259,8 +314,10 @@ namespace Swig { JavaExceptionMessage(JNIEnv *jenv, jthrowable throwable) : message_(jenv, exceptionMessageFromThrowable(jenv, throwable)) { } - const char *message() const { - return message_.c_str("Could not get exception message in JavaExceptionMessage"); + // Return a C string of the exception message in the jthrowable passed in the constructor + // If no message is available, null_string is return instead + const char *message(const char *null_string = "Could not get exception message in JavaExceptionMessage") const { + return message_.c_str(null_string); } private: @@ -294,10 +351,11 @@ namespace Swig { public: // Construct exception from a Java throwable - DirectorException(JNIEnv *jenv, jthrowable throwable) : classname_(0), msg_(0) { + DirectorException(JNIEnv *jenv, jthrowable throwable) : jenv_(jenv), throwable_(throwable), classname_(0), msg_(0) { // Call Java method Object.getClass().getName() to obtain the throwable's class name (delimited by '/') - if (throwable) { + if (jenv && throwable) { + jenv->ExceptionClear(); // Cannot invoke methods with any pending exceptions jclass throwclz = jenv->GetObjectClass(throwable); if (throwclz) { jclass clzclz = jenv->GetObjectClass(throwclz); @@ -318,11 +376,11 @@ namespace Swig { } JavaExceptionMessage exceptionmsg(jenv, throwable); - msg_ = copystr(exceptionmsg.message()); + msg_ = copystr(exceptionmsg.message(0)); } // More general constructor for handling as a java.lang.RuntimeException - DirectorException(const char *msg) : classname_(0), msg_(copystr(msg ? msg : "Unspecified DirectorException message")) { + DirectorException(const char *msg) : jenv_(0), throwable_(0), classname_(0), msg_(msg ? copystr(msg) : 0) { } ~DirectorException() throw() { @@ -331,31 +389,53 @@ namespace Swig { } const char *what() const throw() { - return msg_; + return msg_ ? msg_ : "Unspecified DirectorException message"; } // Reconstruct and raise/throw the Java Exception that caused the DirectorException // Note that any error in the JNI exception handling results in a Java RuntimeException - void raiseJavaException(JNIEnv *jenv) const { + void throwException(JNIEnv *jenv) const { if (jenv) { - jenv->ExceptionClear(); + if (jenv == jenv_ && throwable_) { + // Throw original exception if not already pending + jthrowable throwable = jenv->ExceptionOccurred(); + if (throwable && jenv->IsSameObject(throwable, throwable_) == JNI_FALSE) { + jenv->ExceptionClear(); + throwable = 0; + } + if (!throwable) + jenv->Throw(throwable_); + } else { + // Try and reconstruct original exception, but original stacktrace is not reconstructed + jenv->ExceptionClear(); - jmethodID ctorMethodID = 0; - jclass throwableclass = 0; - if (classname_) { - throwableclass = jenv->FindClass(classname_); - if (throwableclass) - ctorMethodID = jenv->GetMethodID(throwableclass, "", "(Ljava/lang/String;)V"); - } + jmethodID ctorMethodID = 0; + jclass throwableclass = 0; + if (classname_) { + throwableclass = jenv->FindClass(classname_); + if (throwableclass) + ctorMethodID = jenv->GetMethodID(throwableclass, "", "(Ljava/lang/String;)V"); + } - if (ctorMethodID) { - jenv->ThrowNew(throwableclass, what()); - } else { - SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, what()); - } + if (ctorMethodID) { + jenv->ThrowNew(throwableclass, what()); + } else { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, what()); + } + } } } + // Deprecated - use throwException + void raiseJavaException(JNIEnv *jenv) const { + throwException(jenv); + } + + // Create and throw the DirectorException + static void raise(JNIEnv *jenv, jthrowable throwable) { + throw DirectorException(jenv, throwable); + } + private: static char *copypath(const char *srcmsg) { char *target = copystr(srcmsg); @@ -376,11 +456,14 @@ namespace Swig { return target; } + JNIEnv *jenv_; + jthrowable throwable_; const char *classname_; const char *msg_; }; // Helper method to determine if a Java throwable matches a particular Java class type + // Note side effect of clearing any pending exceptions SWIGINTERN bool ExceptionMatches(JNIEnv *jenv, jthrowable throwable, const char *classname) { bool matches = false; diff --git a/Lib/java/java.swg b/Lib/java/java.swg index d763c5e6f..e9309331a 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -54,6 +54,14 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { } } +%fragment("SWIG_JavaIntFromSize_t", "header") { +/* Check for overflow converting to Java int (always signed 32-bit) from (unsigned variable-bit) size_t */ +SWIGINTERN jint SWIG_JavaIntFromSize_t(size_t size) { + static const jint JINT_MAX = 0x7FFFFFFF; + return (size > (size_t)JINT_MAX) ? -1 : (jint)size; +} +} + /* Primitive types */ %typemap(jni) bool, const bool & "jboolean" %typemap(jni) char, const char & "jchar" @@ -103,6 +111,21 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(jstype) double, const double & "double" %typemap(jstype) void "void" +%typemap(jboxtype) bool, const bool & "Boolean" +%typemap(jboxtype) char, const char & "Character" +%typemap(jboxtype) signed char, const signed char & "Byte" +%typemap(jboxtype) unsigned char, const unsigned char & "Short" +%typemap(jboxtype) short, const short & "Short" +%typemap(jboxtype) unsigned short, const unsigned short & "Integer" +%typemap(jboxtype) int, const int & "Integer" +%typemap(jboxtype) unsigned int, const unsigned int & "Long" +%typemap(jboxtype) long, const long & "Integer" +%typemap(jboxtype) unsigned long, const unsigned long & "Long" +%typemap(jboxtype) long long, const long long & "Long" +%typemap(jboxtype) unsigned long long, const unsigned long long & "java.math.BigInteger" +%typemap(jboxtype) float, const float & "Float" +%typemap(jboxtype) double, const double & "Double" + %typemap(jni) char *, char *&, char[ANY], char[] "jstring" %typemap(jtype) char *, char *&, char[ANY], char[] "String" %typemap(jstype) char *, char *&, char[ANY], char[] "String" @@ -137,7 +160,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(jtype) jfloat "float" %typemap(jtype) jdouble "double" %typemap(jtype) jstring "String" -%typemap(jtype) jobject "Object" +%typemap(jtype) jobject "java.lang.Object" %typemap(jtype) jbooleanArray "boolean[]" %typemap(jtype) jcharArray "char[]" %typemap(jtype) jbyteArray "byte[]" @@ -146,7 +169,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(jtype) jlongArray "long[]" %typemap(jtype) jfloatArray "float[]" %typemap(jtype) jdoubleArray "double[]" -%typemap(jtype) jobjectArray "Object[]" +%typemap(jtype) jobjectArray "java.lang.Object[]" %typemap(jstype) jboolean "boolean" %typemap(jstype) jchar "char" @@ -157,7 +180,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(jstype) jfloat "float" %typemap(jstype) jdouble "double" %typemap(jstype) jstring "String" -%typemap(jstype) jobject "Object" +%typemap(jstype) jobject "java.lang.Object" %typemap(jstype) jbooleanArray "boolean[]" %typemap(jstype) jcharArray "char[]" %typemap(jstype) jbyteArray "byte[]" @@ -166,12 +189,13 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(jstype) jlongArray "long[]" %typemap(jstype) jfloatArray "float[]" %typemap(jstype) jdoubleArray "double[]" -%typemap(jstype) jobjectArray "Object[]" +%typemap(jstype) jobjectArray "java.lang.Object[]" /* Non primitive types */ %typemap(jni) SWIGTYPE "jlong" %typemap(jtype) SWIGTYPE "long" %typemap(jstype) SWIGTYPE "$&javaclassname" +%typemap(jboxtype) SWIGTYPE "$typemap(jstype, $1_type)" %typemap(jni) SWIGTYPE [] "jlong" %typemap(jtype) SWIGTYPE [] "long" @@ -363,11 +387,13 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0); bigint = JCALL3(NewObject, jenv, clazz, mid, ba); + JCALL1(DeleteLocalRef, jenv, ba); $result = bigint; } /* Convert to BigInteger (see out typemap) */ -%typemap(directorin, descriptor="Ljava/math/BigInteger;") unsigned long long, const unsigned long long & { +%typemap(directorin, descriptor="Ljava/math/BigInteger;", noblock=1) unsigned long long, const unsigned long long & { +{ jbyteArray ba = JCALL1(NewByteArray, jenv, 9); jbyte* bae = JCALL2(GetByteArrayElements, jenv, ba, 0); jclass clazz = JCALL1(FindClass, jenv, "java/math/BigInteger"); @@ -382,8 +408,10 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0); bigint = JCALL3(NewObject, jenv, clazz, mid, ba); + JCALL1(DeleteLocalRef, jenv, ba); $input = bigint; } +Swig::LocalRefGuard $1_refguard(jenv, $input); } %typemap(javadirectorin) unsigned long long "$jniinput" %typemap(javadirectorout) unsigned long long "$javacall" @@ -611,6 +639,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0); bigint = JCALL3(NewObject, jenv, clazz, mid, ba); + JCALL1(DeleteLocalRef, jenv, ba); $result = bigint; } @@ -1022,6 +1051,14 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1); return $null; %} +/* For methods to raise/throw the original Java exception thrown in a director method */ +%typemap(throws) Swig::DirectorException +%{ $1.throwException(jenv); + return $null; %} + +/* Java to C++ DirectorException should already be handled. Suppress warning and do nothing in the + event a user specifies a global: %catches(Swig::DirectorException); */ +%typemap(directorthrows) Swig::DirectorException "" /* Typemaps for code generation in proxy classes and Java type wrapper classes */ @@ -1144,6 +1181,14 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { $1 = ($1_ltype)&temp; %} %typemap(out) SWIGTYPE *const& %{ *($1_ltype)&$result = *$1; %} +%typemap(directorin,descriptor="L$packagepath/$*javaclassname;") SWIGTYPE *const& +%{ *(($1_ltype)&$input) = ($*1_ltype) $1; %} +%typemap(directorout, warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) SWIGTYPE *const& +%{ static $*1_ltype swig_temp; + swig_temp = *($1_ltype)&$input; + $result = &swig_temp; %} +%typemap(javadirectorin) SWIGTYPE *const& "($jniinput == 0) ? null : new $*javaclassname($jniinput, false)" +%typemap(javadirectorout) SWIGTYPE *const& "$*javaclassname.getCPtr($javacall)" /* Typemaps used for the generation of proxy and type wrapper class code */ %typemap(javabase) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) "" @@ -1206,7 +1251,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %} %typemap(javabody) TYPE (CLASS::*) %{ - private String swigCMemberPtr; + private transient String swigCMemberPtr; PTRCTOR_VISIBILITY $javaclassname(String cMemberPtr, @SuppressWarnings("unused") boolean futureUse) { swigCMemberPtr = cMemberPtr; @@ -1228,6 +1273,7 @@ SWIG_JAVABODY_PROXY(protected, protected, SWIGTYPE) SWIG_JAVABODY_TYPEWRAPPER(protected, protected, protected, SWIGTYPE) %typemap(javafinalize) SWIGTYPE %{ + @SuppressWarnings("deprecation") protected void finalize() { delete(); } @@ -1255,7 +1301,7 @@ SWIG_JAVABODY_TYPEWRAPPER(protected, protected, protected, SWIGTYPE) */ %define SWIG_PROXY_CONSTRUCTOR(OWNERSHIP, WEAKREF, TYPENAME...) -%typemap(javaconstruct,directorconnect="\n $imclassname.$javaclazznamedirector_connect(this, swigCPtr, swigCMemOwn, WEAKREF);") TYPENAME { +%typemap(javaconstruct,directorconnect="\n $imclassname.$javaclazznamedirector_connect(this, swigCPtr, OWNERSHIP, WEAKREF);") TYPENAME { this($imcall, OWNERSHIP);$directorconnect } %enddef @@ -1267,7 +1313,7 @@ SWIG_PROXY_CONSTRUCTOR(true, false, TYPENAME) // Set the default for SWIGTYPE: Java owns the C/C++ object. SWIG_PROXY_CONSTRUCTOR(true, true, SWIGTYPE) -%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") SWIGTYPE { +%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized", parameters="") SWIGTYPE { if (swigCPtr != 0) { if (swigCMemOwn) { swigCMemOwn = false; @@ -1277,7 +1323,7 @@ SWIG_PROXY_CONSTRUCTOR(true, true, SWIGTYPE) } } -%typemap(javadestruct_derived, methodname="delete", methodmodifiers="public synchronized") SWIGTYPE { +%typemap(javadestruct_derived, methodname="delete", methodmodifiers="public synchronized", parameters="") SWIGTYPE { if (swigCPtr != 0) { if (swigCMemOwn) { swigCMemOwn = false; @@ -1317,6 +1363,7 @@ SWIG_PROXY_CONSTRUCTOR(true, true, SWIGTYPE) #define %javaexception(exceptionclasses) %feature("except",throws=exceptionclasses) #define %nojavaexception %feature("except","0",throws="") #define %clearjavaexception %feature("except","",throws="") +#define %proxycode %insert("proxycode") %pragma(java) jniclassclassmodifiers="public class" %pragma(java) moduleclassmodifiers="public class" @@ -1332,14 +1379,16 @@ SWIG_PROXY_CONSTRUCTOR(true, true, SWIGTYPE) /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } /* String & length */ -%typemap(jni) (char *STRING, size_t LENGTH) "jbyteArray" -%typemap(jtype) (char *STRING, size_t LENGTH) "byte[]" -%typemap(jstype) (char *STRING, size_t LENGTH) "byte[]" -%typemap(javain) (char *STRING, size_t LENGTH) "$javainput" -%typemap(freearg) (char *STRING, size_t LENGTH) "" -%typemap(in) (char *STRING, size_t LENGTH) { +%typemap(jni) (const char *STRING, size_t LENGTH) "jbyteArray" +%typemap(jtype) (const char *STRING, size_t LENGTH) "byte[]" +%typemap(jstype) (const char *STRING, size_t LENGTH) "byte[]" +%typemap(javain) (const char *STRING, size_t LENGTH) "$javainput" +%typemap(freearg) (const char *STRING, size_t LENGTH) "" +%typemap(in) (const char *STRING, size_t LENGTH) { if ($input) { $1 = ($1_ltype) JCALL2(GetByteArrayElements, jenv, $input, 0); $2 = ($2_type) JCALL1(GetArrayLength, jenv, $input); @@ -1348,18 +1397,26 @@ SWIG_PROXY_CONSTRUCTOR(true, true, SWIGTYPE) $2 = 0; } } +%typemap(argout) (const char *STRING, size_t LENGTH) { + if ($input) JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *)$1, JNI_ABORT); +} +%typemap(directorin, descriptor="[B", noblock=1) (const char *STRING, size_t LENGTH) { + $input = 0; + if ($1) { + $input = JCALL1(NewByteArray, jenv, (jsize)$2); + if (!$input) return $null; + JCALL4(SetByteArrayRegion, jenv, $input, 0, (jsize)$2, (jbyte *)$1); + } + Swig::LocalRefGuard $1_refguard(jenv, $input); +} +%typemap(javadirectorin, descriptor="[B") (const char *STRING, size_t LENGTH) "$jniinput" +%apply (const char *STRING, size_t LENGTH) { (char *STRING, size_t LENGTH) } +/* Enable write-back for non-const version */ %typemap(argout) (char *STRING, size_t LENGTH) { if ($input) JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *)$1, 0); } -%typemap(directorin, descriptor="[B") (char *STRING, size_t LENGTH) { - jbyteArray jb = (jenv)->NewByteArray((jsize)$2); - (jenv)->SetByteArrayRegion(jb, 0, (jsize)$2, (jbyte *)$1); - $input = jb; -} -%typemap(directorargout) (char *STRING, size_t LENGTH) -%{(jenv)->GetByteArrayRegion($input, 0, (jsize)$2, (jbyte *)$1); -(jenv)->DeleteLocalRef($input);%} -%typemap(javadirectorin, descriptor="[B") (char *STRING, size_t LENGTH) "$jniinput" +%typemap(directorargout, noblock=1) (char *STRING, size_t LENGTH) +{ if ($input && $1) JCALL4(GetByteArrayRegion, jenv, $input, 0, (jsize)$2, (jbyte *)$1); } %apply (char *STRING, size_t LENGTH) { (char *STRING, int LENGTH) } /* java keywords */ diff --git a/Lib/java/std_array.i b/Lib/java/std_array.i index cbacfe673..d3436cc66 100644 --- a/Lib/java/std_array.i +++ b/Lib/java/std_array.i @@ -8,15 +8,17 @@ namespace std { template class array { public: - typedef T& reference; - typedef const T& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + array(); array(const array& other); + size_type size() const; %rename(isEmpty) empty; bool empty() const; diff --git a/Lib/java/std_except.i b/Lib/java/std_except.i index 9e23d50e6..91d2f92cf 100644 --- a/Lib/java/std_except.i +++ b/Lib/java/std_except.i @@ -7,6 +7,7 @@ * ----------------------------------------------------------------------------- */ %{ +#include #include %} @@ -16,6 +17,7 @@ namespace std struct exception {}; } +%typemap(throws) std::bad_cast "SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.what());\n return $null;" %typemap(throws) std::bad_exception "SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.what());\n return $null;" %typemap(throws) std::domain_error "SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.what());\n return $null;" %typemap(throws) std::exception "SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.what());\n return $null;" diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i new file mode 100644 index 000000000..1077bd0a0 --- /dev/null +++ b/Lib/java/std_list.i @@ -0,0 +1,225 @@ +/* ----------------------------------------------------------------------------- + * std_list.i + * + * SWIG typemaps for std::list. + * The Java proxy class extends java.util.AbstractSequentialList. The std::list + * container looks and feels much like a java.util.LinkedList from Java. + * ----------------------------------------------------------------------------- */ + +%include + +%{ +#include +#include +%} + +%fragment("SWIG_ListSize", "header", fragment="SWIG_JavaIntFromSize_t") { +SWIGINTERN jint SWIG_ListSize(size_t size) { + jint sz = SWIG_JavaIntFromSize_t(size); + if (sz == -1) + throw std::out_of_range("list size is too large to fit into a Java int"); + return sz; +} +} + +%javamethodmodifiers std::list::begin "private"; +%javamethodmodifiers std::list::insert "private"; +%javamethodmodifiers std::list::doSize "private"; +%javamethodmodifiers std::list::doPreviousIndex "private"; +%javamethodmodifiers std::list::doNextIndex "private"; +%javamethodmodifiers std::list::doHasNext "private"; + +// Match Java style better: +%rename(Iterator) std::list::iterator; + +%nodefaultctor std::list::iterator; + +namespace std { + template class list { + +%typemap(javabase) std::list "java.util.AbstractSequentialList<$typemap(jboxtype, T)>" +%proxycode %{ + public $javaclassname(java.util.Collection c) { + this(); + java.util.ListIterator<$typemap(jboxtype, T)> it = listIterator(0); + // Special case the "copy constructor" here to avoid lots of cross-language calls + for (java.lang.Object o : c) { + it.add(($typemap(jboxtype, T))o); + } + } + + public int size() { + return doSize(); + } + + public boolean add($typemap(jboxtype, T) value) { + addLast(value); + return true; + } + + public java.util.ListIterator<$typemap(jboxtype, T)> listIterator(int index) { + return new java.util.ListIterator<$typemap(jboxtype, T)>() { + private Iterator pos; + private Iterator last; + + private java.util.ListIterator<$typemap(jboxtype, T)> init(int index) { + if (index < 0 || index > $javaclassname.this.size()) + throw new IndexOutOfBoundsException("Index: " + index); + pos = $javaclassname.this.begin(); + pos = pos.advance_unchecked(index); + return this; + } + + public void add($typemap(jboxtype, T) v) { + // Technically we can invalidate last here, but this makes more sense + last = $javaclassname.this.insert(pos, v); + } + + public void set($typemap(jboxtype, T) v) { + if (null == last) { + throw new IllegalStateException(); + } + last.set_unchecked(v); + } + + public void remove() { + if (null == last) { + throw new IllegalStateException(); + } + $javaclassname.this.remove(last); + last = null; + } + + public int previousIndex() { + return $javaclassname.this.doPreviousIndex(pos); + } + + public int nextIndex() { + return $javaclassname.this.doNextIndex(pos); + } + + public $typemap(jboxtype, T) previous() { + if (previousIndex() < 0) { + throw new java.util.NoSuchElementException(); + } + last = pos; + pos = pos.previous_unchecked(); + return last.deref_unchecked(); + } + + public $typemap(jboxtype, T) next() { + if (!hasNext()) { + throw new java.util.NoSuchElementException(); + } + last = pos; + pos = pos.next_unchecked(); + return last.deref_unchecked(); + } + + public boolean hasPrevious() { + // This call to previousIndex() will be much slower than the hasNext() implementation, but it's simpler like this with C++ forward iterators + return previousIndex() != -1; + } + + public boolean hasNext() { + return $javaclassname.this.doHasNext(pos); + } + }.init(index); + } +%} + + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + /* + * We'd actually be better off having the nested class *not* be static in the wrapper + * output, but this doesn't actually remove the $static from the nested class still. + * (This would allow us to somewhat simplify the implementation of the ListIterator + * interface and give "natural" semantics to Java users of the C++ iterator) + */ + //%typemap(javaclassmodifiers) iterator "public class" + //%typemap(javainterfaces) iterator "java.util.ListIterator<$typemap(jboxtype, T)>" + + struct iterator { + %extend { + void set_unchecked(const T &v) { + **$self = v; + } + + iterator next_unchecked() const { + std::list::iterator ret = *$self; + ++ret; + return ret; + } + + iterator previous_unchecked() const { + std::list::iterator ret = *$self; + --ret; + return ret; + } + + T deref_unchecked() const { + return **$self; + } + + iterator advance_unchecked(size_type index) const { + std::list::iterator ret = *$self; + std::advance(ret, index); + return ret; + } + } + }; + + list(); + list(const list& other); + + %rename(isEmpty) empty; + bool empty() const; + void clear(); + %rename(remove) erase; + iterator erase(iterator pos); + %rename(removeLast) pop_back; + void pop_back(); + %rename(removeFirst) pop_front; + void pop_front(); + %rename(addLast) push_back; + void push_back(const T &value); + %rename(addFirst) push_front; + void push_front(const T &value); + iterator begin(); + iterator end(); + iterator insert(iterator pos, const T &value); + + %extend { + %fragment("SWIG_ListSize"); + + list(jint count, const T &value) throw (std::out_of_range) { + if (count < 0) + throw std::out_of_range("list count must be positive"); + return new std::list(static_cast::size_type>(count), value); + } + + jint doSize() const throw (std::out_of_range) { + return SWIG_ListSize(self->size()); + } + + jint doPreviousIndex(const iterator &pos) const throw (std::out_of_range) { + return pos == self->begin() ? -1 : SWIG_ListSize(std::distance(self->begin(), static_cast::const_iterator>(pos))); + } + + jint doNextIndex(const iterator &pos) const throw (std::out_of_range) { + return pos == self->end() ? SWIG_ListSize(self->size()) : SWIG_ListSize(std::distance(self->begin(), static_cast::const_iterator>(pos))); + } + + bool doHasNext(const iterator &pos) const { + return pos != $self->end(); + } + } + }; +} diff --git a/Lib/java/std_map.i b/Lib/java/std_map.i index e7812f38a..6d5ca1aac 100644 --- a/Lib/java/std_map.i +++ b/Lib/java/std_map.i @@ -2,6 +2,8 @@ * std_map.i * * SWIG typemaps for std::map + * The Java proxy class extends java.util.AbstractMap. The std::map + * container looks and feels much like a java.util.HashMap from Java. * ----------------------------------------------------------------------------- */ %include @@ -12,52 +14,200 @@ %{ #include -#include #include %} -// exported class +%fragment("SWIG_MapSize", "header", fragment="SWIG_JavaIntFromSize_t") { + SWIGINTERN jint SWIG_MapSize(size_t size) { + jint sz = SWIG_JavaIntFromSize_t(size); + if (sz == -1) { + throw std::out_of_range("map size is too large to fit into a Java int"); + } + + return sz; + } +} + +%javamethodmodifiers std::map::sizeImpl "private"; +%javamethodmodifiers std::map::containsImpl "private"; +%javamethodmodifiers std::map::putUnchecked "private"; +%javamethodmodifiers std::map::removeUnchecked "private"; +%javamethodmodifiers std::map::find "private"; +%javamethodmodifiers std::map::begin "private"; +%javamethodmodifiers std::map::end "private"; + +%rename(Iterator) std::map::iterator; +%nodefaultctor std::map::iterator; +%javamethodmodifiers std::map::iterator::getNextUnchecked "private"; +%javamethodmodifiers std::map::iterator::isNot "private"; +%javamethodmodifiers std::map::iterator::getKey "private"; +%javamethodmodifiers std::map::iterator::getValue "private"; +%javamethodmodifiers std::map::iterator::setValue "private"; namespace std { - template class map { - // add typemaps here - public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef K key_type; - typedef T mapped_type; - map(); - map(const map &); - - unsigned int size() const; - bool empty() const; - void clear(); - %extend { - const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); - if (i != self->end()) - return i->second; - else - throw std::out_of_range("key not found"); - } - void set(const K& key, const T& x) { - (*self)[key] = x; - } - void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); - if (i != self->end()) - self->erase(i); - else - throw std::out_of_range("key not found"); - } - bool has_key(const K& key) { - std::map::iterator i = self->find(key); - return i != self->end(); - } +template > class map { + +%typemap(javabase) std::map< K, T, C > + "java.util.AbstractMap<$typemap(jboxtype, K), $typemap(jboxtype, T)>" + +%proxycode %{ + + public int size() { + return sizeImpl(); + } + + public boolean containsKey(java.lang.Object key) { + if (!(key instanceof $typemap(jboxtype, K))) { + return false; + } + + return containsImpl(($typemap(jboxtype, K))key); + } + + public $typemap(jboxtype, T) get(java.lang.Object key) { + if (!(key instanceof $typemap(jboxtype, K))) { + return null; + } + + Iterator itr = find(($typemap(jboxtype, K)) key); + if (itr.isNot(end())) { + return itr.getValue(); + } + + return null; + } + + public $typemap(jboxtype, T) put($typemap(jboxtype, K) key, $typemap(jboxtype, T) value) { + Iterator itr = find(($typemap(jboxtype, K)) key); + if (itr.isNot(end())) { + $typemap(jboxtype, T) oldValue = itr.getValue(); + itr.setValue(value); + return oldValue; + } else { + putUnchecked(key, value); + return null; + } + } + + public $typemap(jboxtype, T) remove(java.lang.Object key) { + if (!(key instanceof $typemap(jboxtype, K))) { + return null; + } + + Iterator itr = find(($typemap(jboxtype, K)) key); + if (itr.isNot(end())) { + $typemap(jboxtype, T) oldValue = itr.getValue(); + removeUnchecked(itr); + return oldValue; + } else { + return null; + } + } + + public java.util.Set> entrySet() { + java.util.Set> setToReturn = + new java.util.HashSet>(); + + Iterator itr = begin(); + final Iterator end = end(); + while (itr.isNot(end)) { + setToReturn.add(new Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)>() { + private Iterator iterator; + + private Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)> init(Iterator iterator) { + this.iterator = iterator; + return this; } + + public $typemap(jboxtype, K) getKey() { + return iterator.getKey(); + } + + public $typemap(jboxtype, T) getValue() { + return iterator.getValue(); + } + + public $typemap(jboxtype, T) setValue($typemap(jboxtype, T) newValue) { + $typemap(jboxtype, T) oldValue = iterator.getValue(); + iterator.setValue(newValue); + return oldValue; + } + }.init(itr)); + itr = itr.getNextUnchecked(); + } + + return setToReturn; + } +%} + + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + map(); + map(const map& other); + + struct iterator { + %typemap(javaclassmodifiers) iterator "protected class" + %extend { + std::map< K, T, C >::iterator getNextUnchecked() { + std::map< K, T, C >::iterator copy = (*$self); + return ++copy; + } + + bool isNot(iterator other) const { + return (*$self != other); + } + + K getKey() const { + return (*$self)->first; + } + + T getValue() const { + return (*$self)->second; + } + + void setValue(const T& newValue) { + (*$self)->second = newValue; + } + } }; + %rename(isEmpty) empty; + bool empty() const; + void clear(); + iterator find(const K& key); + iterator begin(); + iterator end(); + %extend { + %fragment("SWIG_MapSize"); + + jint sizeImpl() const throw (std::out_of_range) { + return SWIG_MapSize(self->size()); + } + + bool containsImpl(const K& key) { + return (self->count(key) > 0); + } + + void putUnchecked(const K& key, const T& value) { + (*self)[key] = value; + } + + void removeUnchecked(const std::map< K, T, C >::iterator itr) { + self->erase(itr); + } + } +}; + // Legacy macros (deprecated) %define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) #warning "specialize_std_map_on_key ignored - macro is deprecated and no longer necessary" diff --git a/Lib/java/std_pair.i b/Lib/java/std_pair.i index fe45ee676..75ad30315 100644 --- a/Lib/java/std_pair.i +++ b/Lib/java/std_pair.i @@ -18,12 +18,15 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; + pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/java/std_set.i b/Lib/java/std_set.i new file mode 100644 index 000000000..73e0c2cf9 --- /dev/null +++ b/Lib/java/std_set.i @@ -0,0 +1,203 @@ +/* ----------------------------------------------------------------------------- + * std_set.i + * + * SWIG typemaps for std::set + * The Java proxy class extends java.util.AbstractSet. The std::set + * container looks and feels much like a java.util.HashSet from Java. + * ----------------------------------------------------------------------------- */ + +%include + +// ------------------------------------------------------------------------ +// std::set +// ------------------------------------------------------------------------ + +%{ +#include +#include +%} + +%fragment("SWIG_SetSize", "header", fragment="SWIG_JavaIntFromSize_t") { + SWIGINTERN jint SWIG_SetSize(size_t size) { + jint sz = SWIG_JavaIntFromSize_t(size); + if (sz == -1) { + throw std::out_of_range("set size is too large to fit into a Java int"); + } + + return sz; + } +} + +%javamethodmodifiers std::set::sizeImpl "private"; +%javamethodmodifiers std::set::containsImpl "private"; +%javamethodmodifiers std::set::removeImpl "private"; +%javamethodmodifiers std::set::hasNextImpl "private"; +%javamethodmodifiers std::set::begin "private"; +%javamethodmodifiers std::set::end "private"; + +%rename(Iterator) std::set::iterator; +%nodefaultctor std::set::iterator; +%javamethodmodifiers std::set::iterator::incrementUnchecked "private"; +%javamethodmodifiers std::set::iterator::derefUnchecked "private"; +%javamethodmodifiers std::set::iterator::isNot "private"; + +namespace std { + +template +class set { + +%typemap(javabase) std::set "java.util.AbstractSet<$typemap(jboxtype, T)>" +%proxycode %{ + public $javaclassname(java.util.Collection collection) { + this(); + addAll(collection); + } + + public int size() { + return sizeImpl(); + } + + public boolean add($typemap(jboxtype, T) key) { + return addImpl(key); + } + + public boolean addAll(java.util.Collection collection) { + boolean didAddElement = false; + for (java.lang.Object object : collection) { + didAddElement |= add(($typemap(jboxtype, T))object); + } + + return didAddElement; + } + + public java.util.Iterator<$typemap(jboxtype, T)> iterator() { + return new java.util.Iterator<$typemap(jboxtype, T)>() { + private Iterator curr; + private Iterator end; + + private java.util.Iterator<$typemap(jboxtype, T)> init() { + curr = $javaclassname.this.begin(); + end = $javaclassname.this.end(); + return this; + } + + public $typemap(jboxtype, T) next() { + if (!hasNext()) { + throw new java.util.NoSuchElementException(); + } + + // Save the current position, increment it, + // then return the value at the position before the increment. + final $typemap(jboxtype, T) currValue = curr.derefUnchecked(); + curr.incrementUnchecked(); + return currValue; + } + + public boolean hasNext() { + return curr.isNot(end); + } + }.init(); + } + + public boolean containsAll(java.util.Collection collection) { + for (java.lang.Object object : collection) { + if (!contains(object)) { + return false; + } + } + + return true; + } + + public boolean contains(java.lang.Object object) { + if (!(object instanceof $typemap(jboxtype, T))) { + return false; + } + + return containsImpl(($typemap(jboxtype, T))object); + } + + public boolean removeAll(java.util.Collection collection) { + boolean didRemoveElement = false; + for (java.lang.Object object : collection) { + didRemoveElement |= remove(object); + } + + return didRemoveElement; + } + + public boolean remove(java.lang.Object object) { + if (!(object instanceof $typemap(jboxtype, T))) { + return false; + } + + return removeImpl(($typemap(jboxtype, T))object); + } +%} + + public: + + struct iterator { + %typemap(javaclassmodifiers) iterator "protected class" + %extend { + void incrementUnchecked() { + ++(*$self); + } + + T derefUnchecked() const { + return **$self; + } + + bool isNot(iterator other) const { + return (*$self != other); + } + } + }; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T key_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + set(); + set(const set& other); + + %rename(isEmpty) empty; + bool empty() const; + void clear(); + iterator begin(); + iterator end(); + + %extend { + %fragment("SWIG_SetSize"); + + // Returns whether item was inserted. + bool addImpl(const T& key) { + return self->insert(key).second; + } + + // Returns whether set contains key. + bool containsImpl(const T& key) { + return (self->count(key) > 0); + } + + // Returns whether the item was erased. + bool removeImpl(const T& key) { + return (self->erase(key) > 0); + } + + jint sizeImpl() const throw (std::out_of_range) { + return SWIG_SetSize(self->size()); + } + + bool hasNextImpl(const iterator& itr) const { + return (itr != $self->end()); + } + } +}; + +} diff --git a/Lib/java/std_unordered_map.i b/Lib/java/std_unordered_map.i new file mode 100644 index 000000000..283a9b464 --- /dev/null +++ b/Lib/java/std_unordered_map.i @@ -0,0 +1,211 @@ +/* ----------------------------------------------------------------------------- + * std_unordered_map.i + * + * SWIG typemaps for std::unordered_map + * The Java proxy class extends java.util.AbstractMap. The std::unordered_map + * container looks and feels much like a java.util.HashMap from Java. + * ----------------------------------------------------------------------------- */ + +%include + +// ------------------------------------------------------------------------ +// std::unordered_map +// ------------------------------------------------------------------------ + +%{ +#include +#include +%} + +%fragment("SWIG_MapSize", "header", fragment="SWIG_JavaIntFromSize_t") { + SWIGINTERN jint SWIG_MapSize(size_t size) { + jint sz = SWIG_JavaIntFromSize_t(size); + if (sz == -1) { + throw std::out_of_range("map size is too large to fit into a Java int"); + } + + return sz; + } +} + +%javamethodmodifiers std::unordered_map::sizeImpl "private"; +%javamethodmodifiers std::unordered_map::containsImpl "private"; +%javamethodmodifiers std::unordered_map::putUnchecked "private"; +%javamethodmodifiers std::unordered_map::removeUnchecked "private"; +%javamethodmodifiers std::unordered_map::find "private"; +%javamethodmodifiers std::unordered_map::begin "private"; +%javamethodmodifiers std::unordered_map::end "private"; + +%rename(Iterator) std::unordered_map::iterator; +%nodefaultctor std::unordered_map::iterator; +%javamethodmodifiers std::unordered_map::iterator::getNextUnchecked "private"; +%javamethodmodifiers std::unordered_map::iterator::isNot "private"; +%javamethodmodifiers std::unordered_map::iterator::getKey "private"; +%javamethodmodifiers std::unordered_map::iterator::getValue "private"; +%javamethodmodifiers std::unordered_map::iterator::setValue "private"; + +namespace std { + +template class unordered_map { + +%typemap(javabase) std::unordered_map + "java.util.AbstractMap<$typemap(jboxtype, K), $typemap(jboxtype, T)>" + +%proxycode %{ + + public int size() { + return sizeImpl(); + } + + public boolean containsKey(java.lang.Object key) { + if (!(key instanceof $typemap(jboxtype, K))) { + return false; + } + + return containsImpl(($typemap(jboxtype, K))key); + } + + public $typemap(jboxtype, T) get(java.lang.Object key) { + if (!(key instanceof $typemap(jboxtype, K))) { + return null; + } + + Iterator itr = find(($typemap(jboxtype, K)) key); + if (itr.isNot(end())) { + return itr.getValue(); + } + + return null; + } + + public $typemap(jboxtype, T) put($typemap(jboxtype, K) key, $typemap(jboxtype, T) value) { + Iterator itr = find(($typemap(jboxtype, K)) key); + if (itr.isNot(end())) { + $typemap(jboxtype, T) oldValue = itr.getValue(); + itr.setValue(value); + return oldValue; + } else { + putUnchecked(key, value); + return null; + } + } + + public $typemap(jboxtype, T) remove(java.lang.Object key) { + if (!(key instanceof $typemap(jboxtype, K))) { + return null; + } + + Iterator itr = find(($typemap(jboxtype, K)) key); + if (itr.isNot(end())) { + $typemap(jboxtype, T) oldValue = itr.getValue(); + removeUnchecked(itr); + return oldValue; + } else { + return null; + } + } + + public java.util.Set> entrySet() { + java.util.Set> setToReturn = + new java.util.HashSet>(); + + Iterator itr = begin(); + final Iterator end = end(); + while (itr.isNot(end)) { + setToReturn.add(new Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)>() { + private Iterator iterator; + + private Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)> init(Iterator iterator) { + this.iterator = iterator; + return this; + } + + public $typemap(jboxtype, K) getKey() { + return iterator.getKey(); + } + + public $typemap(jboxtype, T) getValue() { + return iterator.getValue(); + } + + public $typemap(jboxtype, T) setValue($typemap(jboxtype, T) newValue) { + $typemap(jboxtype, T) oldValue = iterator.getValue(); + iterator.setValue(newValue); + return oldValue; + } + }.init(itr)); + itr = itr.getNextUnchecked(); + } + + return setToReturn; + } +%} + + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + unordered_map(); + unordered_map(const unordered_map& other); + + struct iterator { + %typemap(javaclassmodifiers) iterator "protected class" + %extend { + std::unordered_map< K, T >::iterator getNextUnchecked() { + std::unordered_map< K, T >::iterator copy = (*$self); + return ++copy; + } + + bool isNot(iterator other) const { + return (*$self != other); + } + + K getKey() const { + return (*$self)->first; + } + + T getValue() const { + return (*$self)->second; + } + + void setValue(const T& newValue) { + (*$self)->second = newValue; + } + } + }; + + %rename(isEmpty) empty; + bool empty() const; + void clear(); + iterator find(const K& key); + iterator begin(); + iterator end(); + %extend { + %fragment("SWIG_MapSize"); + + jint sizeImpl() const throw (std::out_of_range) { + return SWIG_MapSize(self->size()); + } + + bool containsImpl(const K& key) { + return (self->count(key) > 0); + } + + void putUnchecked(const K& key, const T& value) { + (*self)[key] = value; + } + + void removeUnchecked(const std::unordered_map< K, T >::iterator itr) { + self->erase(itr); + } + } +}; + +} diff --git a/Lib/java/std_unordered_set.i b/Lib/java/std_unordered_set.i new file mode 100644 index 000000000..59726e94d --- /dev/null +++ b/Lib/java/std_unordered_set.i @@ -0,0 +1,199 @@ +/* ----------------------------------------------------------------------------- + * std_unordered_set.i + * + * SWIG typemaps for std::unordered_set + * The Java proxy class extends java.util.AbstractSet. The std::unordered_set + * container looks and feels much like a java.util.HashSet from Java. + * ----------------------------------------------------------------------------- */ + +%include + +// ------------------------------------------------------------------------ +// std::unordered_set +// ------------------------------------------------------------------------ + +%{ +#include +#include +%} + +%fragment("SWIG_UnorderedSetSize", "header", fragment="SWIG_JavaIntFromSize_t") { + SWIGINTERN jint SWIG_UnorderedSetSize(size_t size) { + jint sz = SWIG_JavaIntFromSize_t(size); + if (sz == -1) { + throw std::out_of_range("unordered_set size is too large to fit into a Java int"); + } + + return sz; + } +} + +%javamethodmodifiers std::unordered_set::sizeImpl "private"; +%javamethodmodifiers std::unordered_set::containsImpl "private"; +%javamethodmodifiers std::unordered_set::removeImpl "private"; +%javamethodmodifiers std::unordered_set::hasNextImpl "private"; +%javamethodmodifiers std::unordered_set::begin "private"; +%javamethodmodifiers std::unordered_set::end "private"; + +%rename(Iterator) std::unordered_set::iterator; +%nodefaultctor std::unordered_set::iterator; +%javamethodmodifiers std::unordered_set::iterator::incrementUnchecked "private"; +%javamethodmodifiers std::unordered_set::iterator::derefUnchecked "private"; +%javamethodmodifiers std::unordered_set::iterator::isNot "private"; + +namespace std { + +template +class unordered_set { + +%typemap(javabase) std::unordered_set "java.util.AbstractSet<$typemap(jboxtype, Key)>" +%proxycode %{ + public $javaclassname(java.util.Collection collection) { + this(); + addAll(collection); + } + + public int size() { + return sizeImpl(); + } + + public boolean addAll(java.util.Collection collection) { + boolean didAddElement = false; + for (java.lang.Object object : collection) { + didAddElement |= add(($typemap(jboxtype, Key))object); + } + + return didAddElement; + } + + public java.util.Iterator<$typemap(jboxtype, Key)> iterator() { + return new java.util.Iterator<$typemap(jboxtype, Key)>() { + private Iterator curr; + private Iterator end; + + private java.util.Iterator<$typemap(jboxtype, Key)> init() { + curr = $javaclassname.this.begin(); + end = $javaclassname.this.end(); + return this; + } + + public $typemap(jboxtype, Key) next() { + if (!hasNext()) { + throw new java.util.NoSuchElementException(); + } + + // Save the current position, increment it, + // then return the value at the position before the increment. + final $typemap(jboxtype, Key) currValue = curr.derefUnchecked(); + curr.incrementUnchecked(); + return currValue; + } + + public boolean hasNext() { + return curr.isNot(end); + } + }.init(); + } + + public boolean containsAll(java.util.Collection collection) { + for (java.lang.Object object : collection) { + if (!contains(object)) { + return false; + } + } + + return true; + } + + public boolean contains(java.lang.Object object) { + if (!(object instanceof $typemap(jboxtype, Key))) { + return false; + } + + return containsImpl(($typemap(jboxtype, Key))object); + } + + public boolean removeAll(java.util.Collection collection) { + boolean didRemoveElement = false; + for (java.lang.Object object : collection) { + didRemoveElement |= remove(object); + } + + return didRemoveElement; + } + + public boolean remove(java.lang.Object object) { + if (!(object instanceof $typemap(jboxtype, Key))) { + return false; + } + + return removeImpl(($typemap(jboxtype, Key))object); + } +%} + + public: + + struct iterator { + %typemap(javaclassmodifiers) iterator "protected class" + %extend { + void incrementUnchecked() { + ++(*$self); + } + + Key derefUnchecked() const { + return **$self; + } + + bool isNot(iterator other) const { + return (*$self != other); + } + } + }; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef Key value_type; + typedef Key key_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + unordered_set(); + unordered_set(const unordered_set& other); + + %rename(isEmpty) empty; + bool empty() const; + void clear(); + iterator begin(); + iterator end(); + + %extend { + %fragment("SWIG_UnorderedSetSize"); + + // Returns whether item was inserted. + bool add(const Key& key) { + return self->insert(key).second; + } + + // Returns whether set contains key. + bool containsImpl(const Key& key) { + return (self->count(key) > 0); + } + + // Returns whether the item was erased. + bool removeImpl(const Key& key) { + return (self->erase(key) > 0); + } + + jint sizeImpl() const throw (std::out_of_range) { + return SWIG_UnorderedSetSize(self->size()); + } + + bool hasNextImpl(const iterator& itr) const { + return (itr != $self->end()); + } + } +}; + +} diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index 971b426a1..60ee23ebb 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -1,5 +1,10 @@ /* ----------------------------------------------------------------------------- * std_vector.i + * + * SWIG typemaps for std::vector. + * The Java proxy class extends java.util.AbstractList and implements + * java.util.RandomAccess. The std::vector container looks and feels much like a + * java.util.ArrayList from Java. * ----------------------------------------------------------------------------- */ %include @@ -9,77 +14,172 @@ #include %} -namespace std { - - template class vector { - public: - typedef size_t size_type; - typedef T value_type; - typedef const value_type& const_reference; - vector(); - vector(size_type n); - size_type size() const; - size_type capacity() const; - void reserve(size_type n); - %rename(isEmpty) empty; - bool empty() const; - void clear(); - %rename(add) push_back; - void push_back(const value_type& x); - %extend { - const_reference get(int i) throw (std::out_of_range) { - int size = int(self->size()); - if (i>=0 && isize()); - if (i>=0 && i "java.util.AbstractList<$typemap(jboxtype, CTYPE)>" +%typemap(javainterfaces) std::vector< CTYPE > "java.util.RandomAccess" +%proxycode %{ + public $javaclassname($typemap(jstype, CTYPE)[] initialElements) { + this(); + reserve(initialElements.length); + + for ($typemap(jstype, CTYPE) element : initialElements) { + add(element); + } + } + + public $javaclassname(Iterable<$typemap(jboxtype, CTYPE)> initialElements) { + this(); + for ($typemap(jstype, CTYPE) element : initialElements) { + add(element); + } + } + + public $typemap(jboxtype, CTYPE) get(int index) { + return doGet(index); + } + + public $typemap(jboxtype, CTYPE) set(int index, $typemap(jboxtype, CTYPE) e) { + return doSet(index, e); + } + + public boolean add($typemap(jboxtype, CTYPE) e) { + modCount++; + doAdd(e); + return true; + } + + public void add(int index, $typemap(jboxtype, CTYPE) e) { + modCount++; + doAdd(index, e); + } + + public $typemap(jboxtype, CTYPE) remove(int index) { + modCount++; + return doRemove(index); + } + + protected void removeRange(int fromIndex, int toIndex) { + modCount++; + doRemoveRange(fromIndex, toIndex); + } + + public int size() { + return doSize(); + } +%} + + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef CTYPE value_type; + typedef CTYPE *pointer; + typedef CTYPE const *const_pointer; + typedef CTYPE &reference; + typedef CONST_REFERENCE const_reference; + + vector(); + vector(const vector &other); + + size_type capacity() const; + void reserve(size_type n) throw (std::length_error); + %rename(isEmpty) empty; + bool empty() const; + void clear(); + %extend { + %fragment("SWIG_VectorSize"); + + vector(jint count, const CTYPE &value) throw (std::out_of_range) { + if (count < 0) + throw std::out_of_range("vector count must be positive"); + return new std::vector< CTYPE >(static_cast::size_type>(count), value); + } + + jint doSize() const throw (std::out_of_range) { + return SWIG_VectorSize(self->size()); + } + + void doAdd(const value_type& x) { + self->push_back(x); + } + + void doAdd(jint index, const value_type& x) throw (std::out_of_range) { + jint size = static_cast(self->size()); + if (0 <= index && index <= size) { + self->insert(self->begin() + index, x); + } else { + throw std::out_of_range("vector index out of range"); } + } + + value_type doRemove(jint index) throw (std::out_of_range) { + jint size = static_cast(self->size()); + if (0 <= index && index < size) { + CTYPE const old_value = (*self)[index]; + self->erase(self->begin() + index); + return old_value; + } else { + throw std::out_of_range("vector index out of range"); + } + } + + CONST_REFERENCE doGet(jint index) throw (std::out_of_range) { + jint size = static_cast(self->size()); + if (index >= 0 && index < size) + return (*self)[index]; + else + throw std::out_of_range("vector index out of range"); + } + + value_type doSet(jint index, const value_type& val) throw (std::out_of_range) { + jint size = static_cast(self->size()); + if (index >= 0 && index < size) { + CTYPE const old_value = (*self)[index]; + (*self)[index] = val; + return old_value; + } + else + throw std::out_of_range("vector index out of range"); + } + + void doRemoveRange(jint fromIndex, jint toIndex) throw (std::out_of_range) { + jint size = static_cast(self->size()); + if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) { + self->erase(self->begin() + fromIndex, self->begin() + toIndex); + } else { + throw std::out_of_range("vector index out of range"); + } + } + } +%enddef + +%javamethodmodifiers std::vector::doSize "private"; +%javamethodmodifiers std::vector::doAdd "private"; +%javamethodmodifiers std::vector::doGet "private"; +%javamethodmodifiers std::vector::doSet "private"; +%javamethodmodifiers std::vector::doRemove "private"; +%javamethodmodifiers std::vector::doRemoveRange "private"; + +namespace std { + + template class vector { + SWIG_STD_VECTOR_MINIMUM_INTERNAL(T, const value_type&) }; // bool specialization template<> class vector { - public: - typedef size_t size_type; - typedef bool value_type; - typedef bool const_reference; - vector(); - vector(size_type n); - size_type size() const; - size_type capacity() const; - void reserve(size_type n); - %rename(isEmpty) empty; - bool empty() const; - void clear(); - %rename(add) push_back; - void push_back(const value_type& x); - %extend { - bool get(int i) throw (std::out_of_range) { - int size = int(self->size()); - if (i>=0 && isize()); - if (i>=0 && iReleaseStringChars($input, $1_pstr); %} -%typemap(directorin,descriptor="Ljava/lang/String;") wstring { +%typemap(directorin,descriptor="Ljava/lang/String;") wstring %{ jsize $1_len = $1.length(); - jchar *conv_buf = new jchar[$1_len]; + jchar *$1_conv_buf = new jchar[$1_len]; for (jsize i = 0; i < $1_len; ++i) { - conv_buf[i] = (jchar)$1[i]; + $1_conv_buf[i] = (jchar)$1[i]; } - $input = jenv->NewString(conv_buf, $1_len); - delete [] conv_buf; -} + $input = jenv->NewString($1_conv_buf, $1_len); + Swig::LocalRefGuard $1_refguard(jenv, $input); + delete [] $1_conv_buf; +%} %typemap(out) wstring %{jsize $1_len = $1.length(); @@ -136,15 +137,16 @@ class wstring; $result = &$1_str; jenv->ReleaseStringChars($input, $1_pstr); %} -%typemap(directorin,descriptor="Ljava/lang/String;") const wstring & { +%typemap(directorin,descriptor="Ljava/lang/String;") const wstring & %{ jsize $1_len = $1.length(); - jchar *conv_buf = new jchar[$1_len]; + jchar *$1_conv_buf = new jchar[$1_len]; for (jsize i = 0; i < $1_len; ++i) { - conv_buf[i] = (jchar)($1)[i]; + $1_conv_buf[i] = (jchar)($1)[i]; } - $input = jenv->NewString(conv_buf, $1_len); - delete [] conv_buf; -} + $input = jenv->NewString($1_conv_buf, $1_len); + Swig::LocalRefGuard $1_refguard(jenv, $input); + delete [] $1_conv_buf; +%} %typemap(out) const wstring & %{jsize $1_len = $1->length(); diff --git a/Lib/java/typemaps.i b/Lib/java/typemaps.i index 041cb24e0..e130c1930 100644 --- a/Lib/java/typemaps.i +++ b/Lib/java/typemaps.i @@ -187,6 +187,8 @@ There are no char *OUTPUT typemaps, however you can apply the signed char * type %typemap(jtype) TYPE *OUTPUT, TYPE &OUTPUT "JTYPE[]" %typemap(jstype) TYPE *OUTPUT, TYPE &OUTPUT "JTYPE[]" %typemap(javain) TYPE *OUTPUT, TYPE &OUTPUT "$javainput" +%typemap(javadirectorin) TYPE *OUTPUT, TYPE &OUTPUT "$jniinput" +%typemap(javadirectorout) TYPE *OUTPUT, TYPE &OUTPUT "$javacall" %typemap(in) TYPE *OUTPUT($*1_ltype temp), TYPE &OUTPUT($*1_ltype temp) { @@ -204,29 +206,57 @@ There are no char *OUTPUT typemaps, however you can apply the signed char * type %typemap(freearg) TYPE *OUTPUT, TYPE &OUTPUT "" -%typemap(argout) TYPE *OUTPUT, TYPE &OUTPUT +%typemap(argout) TYPE *OUTPUT, TYPE &OUTPUT { JNITYPE jvalue = (JNITYPE)temp$argnum; JCALL4(Set##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &jvalue); } +%typemap(directorin,descriptor=JNIDESC) TYPE &OUTPUT %{ + $input = JCALL1(New##JAVATYPE##Array, jenv, 1); + if (!$input) return $null; + Swig::LocalRefGuard $1_refguard(jenv, $input); %} + +%typemap(directorin,descriptor=JNIDESC) TYPE *OUTPUT %{ + if ($1) { + $input = JCALL1(New##JAVATYPE##Array, jenv, 1); + if (!$input) return $null; + } + Swig::LocalRefGuard $1_refguard(jenv, $input); %} + +%typemap(directorargout, noblock=1) TYPE &OUTPUT +{ + JNITYPE $1_jvalue; + JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + $result = ($*1_ltype)$1_jvalue; +} + +%typemap(directorargout, noblock=1) TYPE *OUTPUT +{ + if ($result) { + JNITYPE $1_jvalue; + JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + *$result = ($*1_ltype)$1_jvalue; + } +} + %typemap(typecheck) TYPE *OUTPUT = TYPECHECKTYPE; %typemap(typecheck) TYPE &OUTPUT = TYPECHECKTYPE; %enddef -OUTPUT_TYPEMAP(bool, jboolean, boolean, Boolean, "[Ljava/lang/Boolean;", jbooleanArray); -OUTPUT_TYPEMAP(signed char, jbyte, byte, Byte, "[Ljava/lang/Byte;", jbyteArray); -OUTPUT_TYPEMAP(unsigned char, jshort, short, Short, "[Ljava/lang/Short;", jshortArray); -OUTPUT_TYPEMAP(short, jshort, short, Short, "[Ljava/lang/Short;", jshortArray); -OUTPUT_TYPEMAP(unsigned short, jint, int, Int, "[Ljava/lang/Integer;", jintArray); -OUTPUT_TYPEMAP(int, jint, int, Int, "[Ljava/lang/Integer;", jintArray); -OUTPUT_TYPEMAP(unsigned int, jlong, long, Long, "[Ljava/lang/Long;", jlongArray); -OUTPUT_TYPEMAP(long, jint, int, Int, "[Ljava/lang/Integer;", jintArray); -OUTPUT_TYPEMAP(unsigned long, jlong, long, Long, "[Ljava/lang/Long;", jlongArray); -OUTPUT_TYPEMAP(long long, jlong, long, Long, "[Ljava/lang/Long;", jlongArray); -OUTPUT_TYPEMAP(unsigned long long, jobject, java.math.BigInteger, NOTUSED, "[Ljava/lang/BigInteger;", SWIGBIGINTEGERARRAY); -OUTPUT_TYPEMAP(float, jfloat, float, Float, "[Ljava/lang/Float;", jfloatArray); -OUTPUT_TYPEMAP(double, jdouble, double, Double, "[Ljava/lang/Double;", jdoubleArray); +OUTPUT_TYPEMAP(bool, jboolean, boolean, Boolean, "[Z", jbooleanArray); +OUTPUT_TYPEMAP(signed char, jbyte, byte, Byte, "[B", jbyteArray); +OUTPUT_TYPEMAP(unsigned char, jshort, short, Short, "[S", jshortArray); +OUTPUT_TYPEMAP(short, jshort, short, Short, "[S", jshortArray); +OUTPUT_TYPEMAP(unsigned short, jint, int, Int, "[I", jintArray); +OUTPUT_TYPEMAP(int, jint, int, Int, "[I", jintArray); +OUTPUT_TYPEMAP(unsigned int, jlong, long, Long, "[J", jlongArray); +OUTPUT_TYPEMAP(long, jint, int, Int, "[I", jintArray); +OUTPUT_TYPEMAP(unsigned long, jlong, long, Long, "[J", jlongArray); +OUTPUT_TYPEMAP(long long, jlong, long, Long, "[J", jlongArray); +OUTPUT_TYPEMAP(unsigned long long, jobject, java.math.BigInteger, Object, "[Ljava/math/BigInteger;", jobjectArray); +OUTPUT_TYPEMAP(float, jfloat, float, Float, "[F", jfloatArray); +OUTPUT_TYPEMAP(double, jdouble, double, Double, "[D", jdoubleArray); #undef OUTPUT_TYPEMAP @@ -244,6 +274,23 @@ OUTPUT_TYPEMAP(double, jdouble, double, Double, "[Ljava/lang/Double;", jdoubleAr $1 = &temp; } +%typemap(directorargout, noblock=1) bool &OUTPUT +{ + jboolean $1_jvalue; + JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + $result = $1_jvalue ? true : false; +} + +%typemap(directorargout, noblock=1) bool *OUTPUT +{ + if ($result) { + jboolean $1_jvalue; + JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + *$result = $1_jvalue ? true : false; + } +} + + /* Convert to BigInteger - byte array holds number in 2's complement big endian format */ /* Use first element in BigInteger array for output */ /* Overrides the typemap in the OUTPUT_TYPEMAP macro */ @@ -262,6 +309,7 @@ OUTPUT_TYPEMAP(double, jdouble, double, Double, "[Ljava/lang/Double;", jdoubleAr JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0); bigint = JCALL3(NewObject, jenv, clazz, mid, ba); + JCALL1(DeleteLocalRef, jenv, ba); JCALL3(SetObjectArrayElement, jenv, $input, 0, bigint); } @@ -330,6 +378,8 @@ There are no char *INOUT typemaps, however you can apply the signed char * typem %typemap(jtype) TYPE *INOUT, TYPE &INOUT "JTYPE[]" %typemap(jstype) TYPE *INOUT, TYPE &INOUT "JTYPE[]" %typemap(javain) TYPE *INOUT, TYPE &INOUT "$javainput" +%typemap(javadirectorin) TYPE *INOUT, TYPE &INOUT "$jniinput" +%typemap(javadirectorout) TYPE *INOUT, TYPE &INOUT "$javacall" %typemap(in) TYPE *INOUT, TYPE &INOUT { if (!$input) { @@ -348,24 +398,54 @@ There are no char *INOUT typemaps, however you can apply the signed char * typem %typemap(argout) TYPE *INOUT, TYPE &INOUT { JCALL3(Release##JAVATYPE##ArrayElements, jenv, $input, (JNITYPE *)$1, 0); } +%typemap(directorin,descriptor=JNIDESC) TYPE &INOUT %{ + $input = JCALL1(New##JAVATYPE##Array, jenv, 1); + if (!$input) return $null; + JNITYPE $1_jvalue = (JNITYPE)$1; + JCALL4(Set##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + Swig::LocalRefGuard $1_refguard(jenv, $input); %} + +%typemap(directorin,descriptor=JNIDESC) TYPE *INOUT %{ + if ($1) { + $input = JCALL1(New##JAVATYPE##Array, jenv, 1); + if (!$input) return $null; + JNITYPE $1_jvalue = (JNITYPE)*$1; + JCALL4(Set##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + } + Swig::LocalRefGuard $1_refguard(jenv, $input); %} + +%typemap(directorargout, noblock=1) TYPE &INOUT +{ + JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + $result = ($*1_ltype)$1_jvalue; +} + +%typemap(directorargout, noblock=1) TYPE *INOUT +{ + if ($result) { + JNITYPE $1_jvalue; + JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + *$result = ($*1_ltype)$1_jvalue; + } +} %typemap(typecheck) TYPE *INOUT = TYPECHECKTYPE; %typemap(typecheck) TYPE &INOUT = TYPECHECKTYPE; %enddef -INOUT_TYPEMAP(bool, jboolean, boolean, Boolean, "[Ljava/lang/Boolean;", jbooleanArray); -INOUT_TYPEMAP(signed char, jbyte, byte, Byte, "[Ljava/lang/Byte;", jbyteArray); -INOUT_TYPEMAP(unsigned char, jshort, short, Short, "[Ljava/lang/Short;", jshortArray); -INOUT_TYPEMAP(short, jshort, short, Short, "[Ljava/lang/Short;", jshortArray); -INOUT_TYPEMAP(unsigned short, jint, int, Int, "[Ljava/lang/Integer;", jintArray); -INOUT_TYPEMAP(int, jint, int, Int, "[Ljava/lang/Integer;", jintArray); -INOUT_TYPEMAP(unsigned int, jlong, long, Long, "[Ljava/lang/Long;", jlongArray); -INOUT_TYPEMAP(long, jint, int, Int, "[Ljava/lang/Integer;", jintArray); -INOUT_TYPEMAP(unsigned long, jlong, long, Long, "[Ljava/lang/Long;", jlongArray); -INOUT_TYPEMAP(long long, jlong, long, Long, "[Ljava/lang/Long;", jlongArray); -INOUT_TYPEMAP(unsigned long long, jobject, java.math.BigInteger, NOTUSED, "[Ljava.math.BigInteger;", SWIGBIGINTEGERARRAY); -INOUT_TYPEMAP(float, jfloat, float, Float, "[Ljava/lang/Float;", jfloatArray); -INOUT_TYPEMAP(double, jdouble, double, Double, "[Ljava/lang/Double;", jdoubleArray); +INOUT_TYPEMAP(bool, jboolean, boolean, Boolean, "[Z", jbooleanArray); +INOUT_TYPEMAP(signed char, jbyte, byte, Byte, "[B", jbyteArray); +INOUT_TYPEMAP(unsigned char, jshort, short, Short, "[S", jshortArray); +INOUT_TYPEMAP(short, jshort, short, Short, "[S", jshortArray); +INOUT_TYPEMAP(unsigned short, jint, int, Int, "[I", jintArray); +INOUT_TYPEMAP(int, jint, int, Int, "[I", jintArray); +INOUT_TYPEMAP(unsigned int, jlong, long, Long, "[J", jlongArray); +INOUT_TYPEMAP(long, jint, int, Int, "[I", jintArray); +INOUT_TYPEMAP(unsigned long, jlong, long, Long, "[J", jlongArray); +INOUT_TYPEMAP(long long, jlong, long, Long, "[J", jlongArray); +INOUT_TYPEMAP(unsigned long long, jobject, java.math.BigInteger, Object, "[java/math/BigInteger;", jobjectArray); +INOUT_TYPEMAP(float, jfloat, float, Float, "[F", jfloatArray); +INOUT_TYPEMAP(double, jdouble, double, Double, "[D", jdoubleArray); #undef INOUT_TYPEMAP @@ -390,6 +470,22 @@ INOUT_TYPEMAP(double, jdouble, double, Double, "[Ljava/lang/Double;", jdoubleArr JCALL3(ReleaseBooleanArrayElements, jenv, $input , (jboolean *)jbtemp$argnum, 0); } +%typemap(directorargout, noblock=1) bool &INOUT +{ + JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + $result = $1_jvalue ? true : false; +} + +%typemap(directorargout, noblock=1) bool *INOUT +{ + if ($result) { + jboolean $1_jvalue; + JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + *$result = $1_jvalue ? true : false; + } +} + + /* Override the typemap in the INOUT_TYPEMAP macro for unsigned long long */ %typemap(in) unsigned long long *INOUT ($*1_ltype temp), unsigned long long &INOUT ($*1_ltype temp) { jobject bigint; diff --git a/Lib/java/various.i b/Lib/java/various.i index 76fb2b129..24796ba84 100644 --- a/Lib/java/various.i +++ b/Lib/java/various.i @@ -129,7 +129,7 @@ /* * char *BYTE typemaps. * These are input typemaps for mapping a Java byte[] array to a C char array. - * Note that as a Java array is used and thus passeed by reference, the C routine + * Note that as a Java array is used and thus passed by reference, the C routine * can return data to Java via the parameter. * * Example usage wrapping: diff --git a/Lib/javascript/jsc/javascriptcode.swg b/Lib/javascript/jsc/javascriptcode.swg index d7f5f5212..4050a6ee3 100644 --- a/Lib/javascript/jsc/javascriptcode.swg +++ b/Lib/javascript/jsc/javascriptcode.swg @@ -32,6 +32,7 @@ static JSObjectRef $jswrapper(JSContextRef context, JSObjectRef ctorObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) { SWIG_exception(SWIG_ERROR, "Class $jsname can not be instantiated"); +fail: return 0; } %} @@ -387,7 +388,7 @@ static JSStaticFunction $jsmangledname_functions[] = { * jsc_nspace_declaration: template for a namespace declaration * - $jsnspace: mangled name of the namespace * - $jsglobalvariables: list of variable entries - * - $jsglobalfunctions: list if fuction entries + * - $jsglobalfunctions: list of function entries * ----------------------------------------------------------------------------- */ %fragment ("jsc_nspace_declaration", "templates") %{ diff --git a/Lib/javascript/jsc/javascripthelpers.swg b/Lib/javascript/jsc/javascripthelpers.swg index 405280161..45765433e 100644 --- a/Lib/javascript/jsc/javascripthelpers.swg +++ b/Lib/javascript/jsc/javascripthelpers.swg @@ -53,7 +53,7 @@ SWIGINTERN bool JS_veto_set_variable(JSContextRef context, JSObjectRef thisObjec } else { SWIG_exception(SWIG_ERROR, msg); } - +fail: return false; } diff --git a/Lib/javascript/jsc/javascriptrun.swg b/Lib/javascript/jsc/javascriptrun.swg index 676a45833..4a8fc5be5 100644 --- a/Lib/javascript/jsc/javascriptrun.swg +++ b/Lib/javascript/jsc/javascriptrun.swg @@ -4,7 +4,7 @@ * ---------------------------------------------------------------------------*/ #define SWIG_Error(code, msg) SWIG_JSC_exception(context, exception, code, msg) -#define SWIG_exception(code, msg) SWIG_JSC_exception(context, exception, code, msg) +#define SWIG_exception(code, msg) do { SWIG_JSC_exception(context, exception, code, msg); SWIG_fail; } while (0) #define SWIG_fail goto fail SWIGRUNTIME void SWIG_Javascript_Raise(JSContextRef context, JSValueRef *exception, const char* type) { @@ -150,7 +150,7 @@ SWIGRUNTIME int SWIG_JSC_ConvertPtr(JSContextRef context, JSValueRef valRef, voi /* special case: JavaScript null => C NULL pointer */ if(JSValueIsNull(context, valRef)) { *ptr=0; - return SWIG_OK; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } if(!JSValueIsObject(context, valRef)) { diff --git a/Lib/javascript/jsc/std_complex.i b/Lib/javascript/jsc/std_complex.i index 088a4fe7b..a252e0aa8 100644 --- a/Lib/javascript/jsc/std_complex.i +++ b/Lib/javascript/jsc/std_complex.i @@ -8,6 +8,13 @@ #include %} +namespace std { + %naturalvar complex; + template class complex; + %template() complex; + %template() complex; +} + /* defining the complex as/from converters */ %swig_cplxdbl_convn(std::complex, std::complex, std::real, std::imag) diff --git a/Lib/javascript/jsc/std_map.i b/Lib/javascript/jsc/std_map.i index e7812f38a..9fa10880f 100644 --- a/Lib/javascript/jsc/std_map.i +++ b/Lib/javascript/jsc/std_map.i @@ -20,22 +20,29 @@ namespace std { - template class map { + template > class map { // add typemaps here public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -45,14 +52,14 @@ namespace std { (*self)[key] = x; } void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } } diff --git a/Lib/javascript/jsc/std_pair.i b/Lib/javascript/jsc/std_pair.i index fe45ee676..732347db5 100644 --- a/Lib/javascript/jsc/std_pair.i +++ b/Lib/javascript/jsc/std_pair.i @@ -18,12 +18,14 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/javascript/jsc/std_vector.i b/Lib/javascript/jsc/std_vector.i index 971b426a1..586ac5c60 100644 --- a/Lib/javascript/jsc/std_vector.i +++ b/Lib/javascript/jsc/std_vector.i @@ -14,10 +14,17 @@ namespace std { template class vector { public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef const value_type& const_reference; + vector(); vector(size_type n); + vector(const vector& other); + size_type size() const; size_type capacity() const; void reserve(size_type n); @@ -48,10 +55,17 @@ namespace std { template<> class vector { public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef bool value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef bool const_reference; + vector(); vector(size_type n); + vector(const vector& other); + size_type size() const; size_type capacity() const; void reserve(size_type n); diff --git a/Lib/javascript/v8/javascriptcode.swg b/Lib/javascript/v8/javascriptcode.swg index 0bcb508f3..c4aaf3db0 100644 --- a/Lib/javascript/v8/javascriptcode.swg +++ b/Lib/javascript/v8/javascriptcode.swg @@ -36,6 +36,7 @@ static SwigV8ReturnValue $jswrapper(const SwigV8Arguments &args) { SWIGV8_HANDLESCOPE(); SWIG_exception(SWIG_ERROR, "Class $jsname can not be instantiated"); +fail: SWIGV8_RETURN(SWIGV8_UNDEFINED()); } %} @@ -132,10 +133,13 @@ static void $jswrapper(v8::Isolate *isolate, v8::Persistent object, v SWIGV8_Proxy *proxy = static_cast(parameter); #elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) static void $jswrapper(v8::Isolate *isolate, v8::Persistent *object, SWIGV8_Proxy *proxy) { -#else +#elif (V8_MAJOR_VERSION-0) < 5 static void $jswrapper(const v8::WeakCallbackData &data) { v8::Local object = data.GetValue(); SWIGV8_Proxy *proxy = data.GetParameter(); +#else + static void $jswrapper(const v8::WeakCallbackInfo &data) { + SWIGV8_Proxy *proxy = data.GetParameter(); #endif if(proxy->swigCMemOwn && proxy->swigCObject) { @@ -146,7 +150,9 @@ static void $jswrapper(const v8::WeakCallbackData &dat } delete proxy; +#if (V8_MAJOR_VERSION-0) < 5 object.Clear(); +#endif #if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) object.Dispose(); @@ -154,7 +160,7 @@ static void $jswrapper(const v8::WeakCallbackData &dat object.Dispose(isolate); #elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) object->Dispose(isolate); -#else +#elif (V8_MAJOR_VERSION-0) < 5 object->Dispose(); #endif } @@ -176,10 +182,13 @@ static void $jswrapper(v8::Isolate *isolate, v8::Persistent object, v SWIGV8_Proxy *proxy = static_cast(parameter); #elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) static void $jswrapper(v8::Isolate *isolate, v8::Persistent< v8::Object> *object, SWIGV8_Proxy *proxy) { -#else +#elif (V8_MAJOR_VERSION-0) < 5 static void $jswrapper(const v8::WeakCallbackData &data) { v8::Local object = data.GetValue(); SWIGV8_Proxy *proxy = data.GetParameter(); +#else +static void $jswrapper(const v8::WeakCallbackInfo &data) { + SWIGV8_Proxy *proxy = data.GetParameter(); #endif if(proxy->swigCMemOwn && proxy->swigCObject) { @@ -196,7 +205,7 @@ static void $jswrapper(const v8::WeakCallbackData &dat object->Dispose(isolate); #elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) object->Dispose(); -#else +#elif (V8_MAJOR_VERSION-0) < 5 object.Clear(); #endif } @@ -210,7 +219,11 @@ static void $jswrapper(const v8::WeakCallbackData &dat * ----------------------------------------------------------------------------- */ %fragment("js_getter", "templates") %{ +#if (V8_MAJOR_VERSION-0) < 5 static SwigV8ReturnValue $jswrapper(v8::Local property, const SwigV8PropertyCallbackInfo &info) { +#else +static SwigV8ReturnValue $jswrapper(v8::Local property, const SwigV8PropertyCallbackInfo &info) { +#endif SWIGV8_HANDLESCOPE(); v8::Handle jsresult; @@ -232,8 +245,11 @@ fail: * ----------------------------------------------------------------------------- */ %fragment("js_setter", "templates") %{ -static void $jswrapper(v8::Local property, v8::Local value, - const SwigV8PropertyCallbackInfoVoid &info) { +#if (V8_MAJOR_VERSION-0) < 5 +static void $jswrapper(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid &info) { +#else +static void $jswrapper(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid &info) { +#endif SWIGV8_HANDLESCOPE(); $jslocals diff --git a/Lib/javascript/v8/javascriptcomplex.swg b/Lib/javascript/v8/javascriptcomplex.swg index 1c0107beb..d3b4aaffa 100644 --- a/Lib/javascript/v8/javascriptcomplex.swg +++ b/Lib/javascript/v8/javascriptcomplex.swg @@ -17,7 +17,7 @@ SWIG_From_dec(Type)(%ifcplusplus(const Type&, Type) c) { SWIGV8_HANDLESCOPE_ESC(); - v8::Local vals = SWIGV8_ARRAY_NEW(2); + v8::Local vals = SWIGV8_ARRAY_NEW(); vals->Set(0, SWIG_From(double)(Real(c))); vals->Set(1, SWIG_From(double)(Imag(c))); diff --git a/Lib/javascript/v8/javascripthelpers.swg b/Lib/javascript/v8/javascripthelpers.swg index f9901fb02..80fbd7aa1 100644 --- a/Lib/javascript/v8/javascripthelpers.swg +++ b/Lib/javascript/v8/javascripthelpers.swg @@ -6,11 +6,16 @@ typedef v8::InvocationCallback SwigV8FunctionCallback; typedef v8::AccessorGetter SwigV8AccessorGetterCallback; typedef v8::AccessorSetter SwigV8AccessorSetterCallback; typedef v8::AccessorInfo SwigV8PropertyCallbackInfoVoid; -#else +#elif (V8_MAJOR_VERSION-0) < 5 typedef v8::FunctionCallback SwigV8FunctionCallback; typedef v8::AccessorGetterCallback SwigV8AccessorGetterCallback; typedef v8::AccessorSetterCallback SwigV8AccessorSetterCallback; typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfoVoid; +#else +typedef v8::FunctionCallback SwigV8FunctionCallback; +typedef v8::AccessorNameGetterCallback SwigV8AccessorGetterCallback; +typedef v8::AccessorNameSetterCallback SwigV8AccessorSetterCallback; +typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfoVoid; #endif /** @@ -65,24 +70,43 @@ SWIGRUNTIME void SWIGV8_AddStaticFunction(v8::Handle obj, const char */ SWIGRUNTIME void SWIGV8_AddStaticVariable(v8::Handle obj, const char* symbol, SwigV8AccessorGetterCallback getter, SwigV8AccessorSetterCallback setter) { +#if (V8_MAJOR_VERSION-0) < 5 obj->SetAccessor(SWIGV8_SYMBOL_NEW(symbol), getter, setter); +#else + obj->SetAccessor(SWIGV8_CURRENT_CONTEXT(), SWIGV8_SYMBOL_NEW(symbol), getter, setter); +#endif } -SWIGRUNTIME void JS_veto_set_variable(v8::Local property, v8::Local value, - const SwigV8PropertyCallbackInfoVoid& info) +#if (V8_MAJOR_VERSION-0) < 5 +SWIGRUNTIME void JS_veto_set_variable(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid& info) +#else +SWIGRUNTIME void JS_veto_set_variable(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid& info) +#endif { char buffer[256]; char msg[512]; int res; +#if (V8_MAJOR_VERSION-0) < 5 property->WriteUtf8(buffer, 256); res = sprintf(msg, "Tried to write read-only variable: %s.", buffer); +#else + v8::Local sproperty; + if (property->ToString(SWIGV8_CURRENT_CONTEXT()).ToLocal(&sproperty)) { + SWIGV8_WRITE_UTF8(sproperty, buffer, 256); + res = sprintf(msg, "Tried to write read-only variable: %s.", buffer); + } + else { + res = -1; + } +#endif if(res<0) { SWIG_exception(SWIG_ERROR, "Tried to write read-only variable."); } else { SWIG_exception(SWIG_ERROR, msg); } +fail: ; } %} // v8_helper_functions diff --git a/Lib/javascript/v8/javascriptinit.swg b/Lib/javascript/v8/javascriptinit.swg index 34befa7ce..8faf2dd8e 100644 --- a/Lib/javascript/v8/javascriptinit.swg +++ b/Lib/javascript/v8/javascriptinit.swg @@ -1,21 +1,35 @@ -%insert(init) %{ - +%insert(header) %{ #include +%} + +%insert(init) %{ SWIGRUNTIME void SWIG_V8_SetModule(void *, swig_module_info *swig_module) { v8::Local global_obj = SWIGV8_CURRENT_CONTEXT()->Global(); v8::Local mod = SWIGV8_EXTERNAL_NEW(swig_module); assert(!mod.IsEmpty()); +#if (V8_MAJOR_VERSION-0) < 5 global_obj->SetHiddenValue(SWIGV8_STRING_NEW("swig_module_info_data"), mod); +#else + v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("swig_module_info_data")); + global_obj->SetPrivate(SWIGV8_CURRENT_CONTEXT(), privateKey, mod); +#endif } SWIGRUNTIME swig_module_info * SWIG_V8_GetModule(void *) { v8::Local global_obj = SWIGV8_CURRENT_CONTEXT()->Global(); +#if (V8_MAJOR_VERSION-0) < 5 v8::Local moduleinfo = global_obj->GetHiddenValue(SWIGV8_STRING_NEW("swig_module_info_data")); +#else + v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("swig_module_info_data")); + v8::Local moduleinfo; + if (!global_obj->GetPrivate(SWIGV8_CURRENT_CONTEXT(), privateKey).ToLocal(&moduleinfo)) + return 0; +#endif - if (moduleinfo.IsEmpty()) + if (moduleinfo.IsEmpty() || moduleinfo->IsNull() || moduleinfo->IsUndefined()) { // It's not yet loaded return 0; @@ -23,7 +37,7 @@ SWIG_V8_GetModule(void *) { v8::Local moduleinfo_extern = v8::Local::Cast(moduleinfo); - if (moduleinfo_extern.IsEmpty()) + if (moduleinfo_extern.IsEmpty() || moduleinfo_extern->IsNull() || moduleinfo_extern->IsUndefined()) { // Something's not right return 0; diff --git a/Lib/javascript/v8/javascriptprimtypes.swg b/Lib/javascript/v8/javascriptprimtypes.swg index c0055c48e..f76be983b 100644 --- a/Lib/javascript/v8/javascriptprimtypes.swg +++ b/Lib/javascript/v8/javascriptprimtypes.swg @@ -22,7 +22,7 @@ int SWIG_AsVal_dec(bool)(v8::Handle obj, bool *val) return SWIG_ERROR; } - if (val) *val = obj->BooleanValue(); + if (val) *val = SWIGV8_BOOLEAN_VALUE(obj); return SWIG_OK; } } @@ -44,7 +44,7 @@ int SWIG_AsVal_dec(int)(v8::Handle valRef, int* val) if (!valRef->IsNumber()) { return SWIG_TypeError; } - if(val) *val = valRef->IntegerValue(); + if(val) *val = SWIGV8_INTEGER_VALUE(valRef); return SWIG_OK; } @@ -68,7 +68,7 @@ int SWIG_AsVal_dec(long)(v8::Handle obj, long* val) if (!obj->IsNumber()) { return SWIG_TypeError; } - if(val) *val = (long) obj->IntegerValue(); + if(val) *val = (long) SWIGV8_INTEGER_VALUE(obj); return SWIG_OK; } @@ -95,7 +95,7 @@ int SWIG_AsVal_dec(unsigned long)(v8::Handle obj, unsigned long *val) return SWIG_TypeError; } - long longVal = (long) obj->NumberValue(); + long longVal = (long) SWIGV8_NUMBER_VALUE(obj); if(longVal < 0) { return SWIG_OverflowError; @@ -133,7 +133,7 @@ int SWIG_AsVal_dec(long long)(v8::Handle obj, long long* val) if (!obj->IsNumber()) { return SWIG_TypeError; } - if(val) *val = (long long) obj->IntegerValue(); + if(val) *val = (long long) SWIGV8_INTEGER_VALUE(obj); return SWIG_OK; } @@ -168,7 +168,7 @@ int SWIG_AsVal_dec(unsigned long long)(v8::Handle obj, unsigned long return SWIG_TypeError; } - long long longVal = (long long) obj->NumberValue(); + long long longVal = (long long) SWIGV8_NUMBER_VALUE(obj); if(longVal < 0) { return SWIG_OverflowError; @@ -198,7 +198,7 @@ int SWIG_AsVal_dec(double)(v8::Handle obj, double *val) if(!obj->IsNumber()) { return SWIG_TypeError; } - if(val) *val = obj->NumberValue(); + if(val) *val = SWIGV8_NUMBER_VALUE(obj); return SWIG_OK; } diff --git a/Lib/javascript/v8/javascriptrun.swg b/Lib/javascript/v8/javascriptrun.swg index 57c5afcd6..2452f4040 100644 --- a/Lib/javascript/v8/javascriptrun.swg +++ b/Lib/javascript/v8/javascriptrun.swg @@ -91,13 +91,39 @@ typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfo; #define SWIGV8_SET_CLASS_TEMPL(class_templ, class) class_templ.Reset(v8::Isolate::GetCurrent(), class); #endif +#ifdef NODE_VERSION +#if NODE_VERSION_AT_LEAST(10, 12, 0) +#define SWIG_NODE_AT_LEAST_1012 +#endif +#endif + +//Necessary to check Node.js version because V8 API changes are backported in Node.js +#if (defined(NODE_VERSION) && !defined(SWIG_NODE_AT_LEAST_1012)) || \ + (!defined(NODE_VERSION) && (V8_MAJOR_VERSION-0) < 7) +#define SWIGV8_TO_OBJECT(handle) (handle)->ToObject() +#define SWIGV8_TO_STRING(handle) (handle)->ToString() +#define SWIGV8_NUMBER_VALUE(handle) (handle)->NumberValue() +#define SWIGV8_INTEGER_VALUE(handle) (handle)->IntegerValue() +#define SWIGV8_BOOLEAN_VALUE(handle) (handle)->BooleanValue() +#define SWIGV8_WRITE_UTF8(handle, buffer, len) (handle)->WriteUtf8(buffer, len) +#define SWIGV8_UTF8_LENGTH(handle) (handle)->Utf8Length() +#else +#define SWIGV8_TO_OBJECT(handle) (handle)->ToObject(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked() +#define SWIGV8_TO_STRING(handle) (handle)->ToString(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked() +#define SWIGV8_NUMBER_VALUE(handle) (handle)->NumberValue(SWIGV8_CURRENT_CONTEXT()).ToChecked() +#define SWIGV8_INTEGER_VALUE(handle) (handle)->IntegerValue(SWIGV8_CURRENT_CONTEXT()).ToChecked() +#define SWIGV8_BOOLEAN_VALUE(handle) (handle)->BooleanValue(SWIGV8_CURRENT_CONTEXT()).ToChecked() +#define SWIGV8_WRITE_UTF8(handle, buffer, len) (handle)->WriteUtf8(v8::Isolate::GetCurrent(), buffer, len) +#define SWIGV8_UTF8_LENGTH(handle) (handle)->Utf8Length(v8::Isolate::GetCurrent()) +#endif + /* --------------------------------------------------------------------------- * Error handling * * ---------------------------------------------------------------------------*/ #define SWIG_Error(code, msg) SWIGV8_ErrorHandler.error(code, msg) -#define SWIG_exception(code, msg) SWIGV8_ErrorHandler.error(code, msg) +#define SWIG_exception(code, msg) do { SWIGV8_ErrorHandler.error(code, msg); SWIG_fail; } while (0) #define SWIG_fail goto fail #define SWIGV8_OVERLOAD false @@ -109,11 +135,11 @@ SWIGINTERN void SWIG_V8_Raise(const char *msg) { Note: There are two contexts for handling errors. A static V8ErrorHandler is used in not overloaded methods. For overloaded methods the throwing type checking mechanism is used - during dispatching. As V8 exceptions can not be resetted properly + during dispatching. As V8 exceptions can not be reset properly the trick is to use a dynamic ErrorHandler with same local name as the global one. - - See defintion of SWIG_Error above. + - See definition of SWIG_Error above. - See code templates 'JS_function_dispatcher', 'JS_functionwrapper_overload', and 'JS_function_dispatch_case' in javascriptcode.swg @@ -193,8 +219,10 @@ public: void (*dtor) (v8::Isolate *isolate, v8::Persistent< v8::Value> object, void *parameter); #elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) void (*dtor) (v8::Isolate *isolate, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy); -#else +#elif (V8_MAJOR_VERSION-0) < 5 void (*dtor) (const v8::WeakCallbackData &data); +#else + void (*dtor) (const v8::WeakCallbackInfo &data); #endif }; @@ -241,9 +269,12 @@ SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Isolate *, v8::Persistent< v8::Val SWIGV8_Proxy *proxy = static_cast(parameter); #elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Isolate *, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy) { -#else +#elif (V8_MAJOR_VERSION-0) < 5 SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(const v8::WeakCallbackData &data) { SWIGV8_Proxy *proxy = data.GetParameter(); +#else +SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(const v8::WeakCallbackInfo &data) { + SWIGV8_Proxy *proxy = data.GetParameter(); #endif delete proxy; @@ -253,7 +284,7 @@ SWIGRUNTIME int SWIG_V8_GetInstancePtr(v8::Handle valRef, void **ptr) if(!valRef->IsObject()) { return SWIG_TypeError; } - v8::Handle objRef = valRef->ToObject(); + v8::Handle objRef = SWIGV8_TO_OBJECT(valRef); if(objRef->InternalFieldCount() < 1) return SWIG_ERROR; @@ -312,12 +343,18 @@ SWIGRUNTIME void SWIGV8_SetPrivateData(v8::Handle obj, void *ptr, sw } else { cdata->handle.MakeWeak(cdata, SWIGV8_Proxy_DefaultDtor); } -#else +#elif (V8_MAJOR_VERSION-0) < 5 if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { cdata->handle.SetWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); } else { cdata->handle.SetWeak(cdata, SWIGV8_Proxy_DefaultDtor); } +#else + if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { + cdata->handle.SetWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor, v8::WeakCallbackType::kParameter); + } else { + cdata->handle.SetWeak(cdata, SWIGV8_Proxy_DefaultDtor, v8::WeakCallbackType::kParameter); + } #endif #if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) @@ -336,12 +373,12 @@ SWIGRUNTIME int SWIG_V8_ConvertPtr(v8::Handle valRef, void **ptr, swi /* special case: JavaScript null => C NULL pointer */ if(valRef->IsNull()) { *ptr=0; - return SWIG_OK; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } if(!valRef->IsObject()) { return SWIG_TypeError; } - v8::Handle objRef = valRef->ToObject(); + v8::Handle objRef = SWIGV8_TO_OBJECT(valRef); return SWIG_V8_ConvertInstancePtr(objRef, ptr, info, flags); } @@ -468,10 +505,17 @@ SWIGRUNTIMEINLINE int SwigV8Packed_Check(v8::Handle valRef) { SWIGV8_HANDLESCOPE(); - v8::Handle objRef = valRef->ToObject(); + v8::Handle objRef = SWIGV8_TO_OBJECT(valRef); if(objRef->InternalFieldCount() < 1) return false; +#if (V8_MAJOR_VERSION-0) < 5 v8::Handle flag = objRef->GetHiddenValue(SWIGV8_STRING_NEW("__swig__packed_data__")); - return (flag->IsBoolean() && flag->BooleanValue()); +#else + v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("__swig__packed_data__")); + v8::Local flag; + if (!objRef->GetPrivate(SWIGV8_CURRENT_CONTEXT(), privateKey).ToLocal(&flag)) + return false; +#endif + return (flag->IsBoolean() && SWIGV8_BOOLEAN_VALUE(flag)); } SWIGRUNTIME @@ -481,7 +525,7 @@ swig_type_info *SwigV8Packed_UnpackData(v8::Handle valRef, void *ptr, SwigV8PackedData *sobj; - v8::Handle objRef = valRef->ToObject(); + v8::Handle objRef = SWIGV8_TO_OBJECT(valRef); #if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) v8::Handle cdataRef = objRef->GetInternalField(0); @@ -519,10 +563,13 @@ SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Isolate *isolate, v8::Persist SwigV8PackedData *cdata = static_cast(parameter); #elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Isolate *isolate, v8::Persistent *object, SwigV8PackedData *cdata) { -#else +#elif (V8_MAJOR_VERSION-0) < 5 SWIGRUNTIME void _wrap_SwigV8PackedData_delete(const v8::WeakCallbackData &data) { v8::Local object = data.GetValue(); SwigV8PackedData *cdata = data.GetParameter(); +#else +SWIGRUNTIME void _wrap_SwigV8PackedData_delete(const v8::WeakCallbackInfo &data) { + SwigV8PackedData *cdata = data.GetParameter(); #endif delete cdata; @@ -537,7 +584,7 @@ SWIGRUNTIME void _wrap_SwigV8PackedData_delete(const v8::WeakCallbackDataDispose(isolate); #elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) object->Dispose(); -#else +#elif (V8_MAJOR_VERSION-0) < 5 object.Clear(); #endif } @@ -550,7 +597,12 @@ v8::Handle SWIGV8_NewPackedObj(void *data, size_t size, swig_type_inf // v8::Handle obj = SWIGV8_OBJECT_NEW(); v8::Local obj = SWIGV8_OBJECT_NEW(); +#if (V8_MAJOR_VERSION-0) < 5 obj->SetHiddenValue(SWIGV8_STRING_NEW("__swig__packed_data__"), SWIGV8_BOOLEAN_NEW(true)); +#else + v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("__swig__packed_data__")); + obj->SetPrivate(SWIGV8_CURRENT_CONTEXT(), privateKey, SWIGV8_BOOLEAN_NEW(true)); +#endif #if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) obj->SetPointerInInternalField(0, cdata); @@ -573,9 +625,11 @@ v8::Handle SWIGV8_NewPackedObj(void *data, size_t size, swig_type_inf cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, _wrap_SwigV8PackedData_delete); #elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) cdata->handle.MakeWeak(cdata, _wrap_SwigV8PackedData_delete); -#else +#elif (V8_MAJOR_VERSION-0) < 5 cdata->handle.SetWeak(cdata, _wrap_SwigV8PackedData_delete); // v8::V8::SetWeak(&cdata->handle, cdata, _wrap_SwigV8PackedData_delete); +#else + cdata->handle.SetWeak(cdata, _wrap_SwigV8PackedData_delete, v8::WeakCallbackType::kParameter); #endif #if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) diff --git a/Lib/javascript/v8/javascriptruntime.swg b/Lib/javascript/v8/javascriptruntime.swg index 0e4059326..c78e04efb 100644 --- a/Lib/javascript/v8/javascriptruntime.swg +++ b/Lib/javascript/v8/javascriptruntime.swg @@ -44,6 +44,8 @@ #ifdef BUILDING_NODE_EXTENSION %insert("runtime") %{ #include +//Older version of node.h does not include this +#include %} #endif diff --git a/Lib/javascript/v8/javascriptstrings.swg b/Lib/javascript/v8/javascriptstrings.swg index 65ba20e5a..e767a6d66 100644 --- a/Lib/javascript/v8/javascriptstrings.swg +++ b/Lib/javascript/v8/javascriptstrings.swg @@ -7,11 +7,11 @@ SWIGINTERN int SWIG_AsCharPtrAndSize(v8::Handle valRef, char** cptr, size_t* psize, int *alloc) { if(valRef->IsString()) { - v8::Handle js_str = valRef->ToString(); + v8::Handle js_str = SWIGV8_TO_STRING(valRef); - size_t len = js_str->Utf8Length() + 1; + size_t len = SWIGV8_UTF8_LENGTH(js_str) + 1; char* cstr = new char[len]; - js_str->WriteUtf8(cstr, len); + SWIGV8_WRITE_UTF8(js_str, cstr, len); if(alloc) *alloc = SWIG_NEWOBJ; if(psize) *psize = len; @@ -20,7 +20,7 @@ SWIG_AsCharPtrAndSize(v8::Handle valRef, char** cptr, size_t* psize, return SWIG_OK; } else { if(valRef->IsObject()) { - v8::Handle obj = valRef->ToObject(); + v8::Handle obj = SWIGV8_TO_OBJECT(valRef); // try if the object is a wrapped char[] swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); if (pchar_descriptor) { diff --git a/Lib/javascript/v8/std_complex.i b/Lib/javascript/v8/std_complex.i index 088a4fe7b..a252e0aa8 100644 --- a/Lib/javascript/v8/std_complex.i +++ b/Lib/javascript/v8/std_complex.i @@ -8,6 +8,13 @@ #include %} +namespace std { + %naturalvar complex; + template class complex; + %template() complex; + %template() complex; +} + /* defining the complex as/from converters */ %swig_cplxdbl_convn(std::complex, std::complex, std::real, std::imag) diff --git a/Lib/javascript/v8/std_map.i b/Lib/javascript/v8/std_map.i index e7812f38a..3b8b09369 100644 --- a/Lib/javascript/v8/std_map.i +++ b/Lib/javascript/v8/std_map.i @@ -20,22 +20,28 @@ namespace std { - template class map { + template > class map { // add typemaps here public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -45,14 +51,14 @@ namespace std { (*self)[key] = x; } void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } } diff --git a/Lib/javascript/v8/std_pair.i b/Lib/javascript/v8/std_pair.i index 8d6057223..b72c50b99 100644 --- a/Lib/javascript/v8/std_pair.i +++ b/Lib/javascript/v8/std_pair.i @@ -17,12 +17,14 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/javascript/v8/std_vector.i b/Lib/javascript/v8/std_vector.i index 971b426a1..586ac5c60 100644 --- a/Lib/javascript/v8/std_vector.i +++ b/Lib/javascript/v8/std_vector.i @@ -14,10 +14,17 @@ namespace std { template class vector { public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef const value_type& const_reference; + vector(); vector(size_type n); + vector(const vector& other); + size_type size() const; size_type capacity() const; void reserve(size_type n); @@ -48,10 +55,17 @@ namespace std { template<> class vector { public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef bool value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef bool const_reference; + vector(); vector(size_type n); + vector(const vector& other); + size_type size() const; size_type capacity() const; void reserve(size_type n); diff --git a/Lib/lua/lua.swg b/Lib/lua/lua.swg index 9c21d0812..6db3add6e 100644 --- a/Lib/lua/lua.swg +++ b/Lib/lua/lua.swg @@ -33,7 +33,7 @@ %typemap(consttab) char *, const char *, char [], const char [] {SWIG_LUA_CONSTTAB_STRING("$symname", $value)} -// note: char is treated as a seperate special type +// note: char is treated as a separate special type // signed char & unsigned char are numbers %typemap(consttab) char {SWIG_LUA_CONSTTAB_CHAR("$symname", $value)} diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg index 660dbbf86..9636cdc9b 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -180,8 +180,8 @@ typedef struct swig_elua_entry { * -------------------------------------------------------------------------- */ /* Push the string STR on the Lua stack, like lua_pushstring, but - prefixed with the the location of the innermost Lua call-point - (as formated by luaL_where). */ + prefixed with the location of the innermost Lua call-point + (as formatted by luaL_where). */ SWIGRUNTIME void SWIG_Lua_pusherrstring (lua_State *L, const char *str) { @@ -191,8 +191,8 @@ SWIG_Lua_pusherrstring (lua_State *L, const char *str) } /* Push a formatted string generated from FMT and following args on - the Lua stack, like lua_pushfstring, but prefixed with the the - location of the innermost Lua call-point (as formated by luaL_where). */ + the Lua stack, like lua_pushfstring, but prefixed with the + location of the innermost Lua call-point (as formatted by luaL_where). */ SWIGRUNTIME void SWIG_Lua_pushferrstring (lua_State *L, const char *fmt, ...) { @@ -289,7 +289,7 @@ to tell the two structures apart within SWIG, other than by looking at the type typedef struct { swig_type_info *type; int own; /* 1 if owned & must be destroyed */ - char data[1]; /* arbitary amount of data */ + char data[1]; /* arbitrary amount of data */ } swig_lua_rawdata; /* Common SWIG API */ @@ -1765,7 +1765,12 @@ SWIGRUNTIME int SWIG_Lua_ConvertPtr(lua_State *L,int index,void **ptr,swig_type { swig_lua_userdata *usr; swig_cast_info *cast; - if (lua_isnil(L,index)){*ptr=0; return SWIG_OK;} /* special case: lua nil => NULL pointer */ + /* special case: lua nil => NULL pointer */ + if (lua_isnil(L,index)) + { + *ptr=0; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; + } usr=(swig_lua_userdata*)lua_touserdata(L,index); /* get data */ if (usr) { @@ -1860,7 +1865,7 @@ SWIG_Lua_InstallConstants(lua_State *L, swig_lua_const_info constants[]) { switch(constants[i].type) { case SWIG_LUA_INT: lua_pushstring(L,constants[i].name); - lua_pushinteger(L,(lua_Number)constants[i].lvalue); + lua_pushinteger(L,(lua_Integer)constants[i].lvalue); lua_rawset(L,-3); break; case SWIG_LUA_FLOAT: @@ -1871,7 +1876,7 @@ SWIG_Lua_InstallConstants(lua_State *L, swig_lua_const_info constants[]) { case SWIG_LUA_CHAR: lua_pushstring(L,constants[i].name); { - char c = constants[i].lvalue; + char c = (char)constants[i].lvalue; lua_pushlstring(L,&c,1); } lua_rawset(L,-3); diff --git a/Lib/lua/luaruntime.swg b/Lib/lua/luaruntime.swg index 8df46e8cb..399bb640e 100644 --- a/Lib/lua/luaruntime.swg +++ b/Lib/lua/luaruntime.swg @@ -4,8 +4,9 @@ * all the runtime code for . * ----------------------------------------------------------------------------- */ -%runtime "swigrun.swg"; /* Common C API type-checking code */ -%runtime "luarun.swg"; /* Lua runtime stuff */ +%runtime "swigrun.swg" /* Common C API type-checking code */ +%runtime "swigerrors.swg" /* SWIG errors */ +%runtime "luarun.swg" /* Lua runtime stuff */ %insert(initbeforefunc) "swiginit.swg" diff --git a/Lib/lua/luatypemaps.swg b/Lib/lua/luatypemaps.swg index 5d98e6107..8959f201e 100644 --- a/Lib/lua/luatypemaps.swg +++ b/Lib/lua/luatypemaps.swg @@ -189,7 +189,7 @@ SWIGINTERN int SWIG_lua_isnilstring(lua_State *L, int idx) { // Also needed for object ptrs by const ref // eg A* const& ref_pointer(A* const& a); // found in mixed_types.i -%typemap(in,checkfn="lua_isuserdata") SWIGTYPE *const&($*ltype temp) +%typemap(in,checkfn="SWIG_isptrtype") SWIGTYPE *const&($*ltype temp) %{temp=($*ltype)SWIG_MustGetPtr(L,$input,$*descriptor,0,$argnum,"$symname"); $1=($1_ltype)&temp;%} @@ -235,7 +235,6 @@ $1=($1_ltype)&temp;%} // so the standard wrapping cannot be done // nor can you cast a member function pointer to a void* (obviously) // therefore a special wrapping functions SWIG_ConvertMember() & SWIG_NewMemberObj() were written -#ifdef __cplusplus %typemap(in,checkfn="lua_isuserdata") SWIGTYPE (CLASS::*) %{ if (!SWIG_IsOK(SWIG_ConvertMember(L,$input,(void*)(&$1),sizeof($type),$descriptor))) @@ -246,7 +245,6 @@ $1=($1_ltype)&temp;%} %{ SWIG_NewMemberObj(L,(void*)(&$1),sizeof($type),$descriptor); SWIG_arg++; %} -#endif // void (must be empty without the SWIG_arg++) @@ -329,7 +327,7 @@ parameters match which function %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE & { void *ptr; - if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $1_descriptor, 0)) { + if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $1_descriptor, SWIG_POINTER_NO_NULL)) { $1 = 0; } else { $1 = 1; @@ -338,7 +336,7 @@ parameters match which function %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE && { void *ptr; - if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $1_descriptor, 0)) { + if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $1_descriptor, SWIG_POINTER_NO_NULL)) { $1 = 0; } else { $1 = 1; @@ -347,7 +345,7 @@ parameters match which function %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { void *ptr; - if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $&1_descriptor, 0)) { + if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $&1_descriptor, SWIG_POINTER_NO_NULL)) { $1 = 0; } else { $1 = 1; @@ -369,7 +367,7 @@ parameters match which function %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *const& { void *ptr; - if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $*descriptor, 0)) { + if (SWIG_isptrtype(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $*descriptor, 0)) { $1 = 0; } else { $1 = 1; @@ -386,6 +384,8 @@ parameters match which function /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } // size_t (which is just a unsigned long) %apply unsigned long { size_t }; diff --git a/Lib/lua/std_except.i b/Lib/lua/std_except.i index 160828723..34ab6a1ad 100644 --- a/Lib/lua/std_except.i +++ b/Lib/lua/std_except.i @@ -8,6 +8,7 @@ * ----------------------------------------------------------------------------- */ %{ +#include #include %} %include @@ -27,6 +28,7 @@ namespace std // normally objects which are thrown are returned to the interpreter as errors // (which potentially may have problems if they are not copied) // therefore all classes based upon std::exception are converted to their strings & returned as errors +%typemap(throws) std::bad_cast "SWIG_exception(SWIG_TypeError, $1.what());" %typemap(throws) std::bad_exception "SWIG_exception(SWIG_RuntimeError, $1.what());" %typemap(throws) std::domain_error "SWIG_exception(SWIG_ValueError, $1.what());" %typemap(throws) std::exception "SWIG_exception(SWIG_SystemError, $1.what());" diff --git a/Lib/lua/std_map.i b/Lib/lua/std_map.i index 84b0c74ff..773b6d0c3 100644 --- a/Lib/lua/std_map.i +++ b/Lib/lua/std_map.i @@ -20,22 +20,28 @@ namespace std { - template class map { + template > class map { // add typemaps here public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -45,14 +51,14 @@ namespace std { (*self)[key] = x; } void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } } diff --git a/Lib/lua/std_pair.i b/Lib/lua/std_pair.i index 06728533b..410da9223 100644 --- a/Lib/lua/std_pair.i +++ b/Lib/lua/std_pair.i @@ -7,21 +7,6 @@ %{ #include %} -/* -A really cut down version of the pair class. - -this is not useful on its own - it needs a %template definition with it - -eg. -namespace std { - %template(IntPair) pair; - %template(make_IntPair) make_pair; -} - - -*/ - - namespace std { template struct pair { @@ -30,13 +15,12 @@ namespace std { pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); T first; U second; }; template - pair make_pair(const T&,const U&); - + pair make_pair(const T& first, const U& second); } diff --git a/Lib/lua/std_string.i b/Lib/lua/std_string.i index e9f326b52..b95a8a4a2 100644 --- a/Lib/lua/std_string.i +++ b/Lib/lua/std_string.i @@ -109,7 +109,6 @@ as this is overloaded by the const char* version public: string(); string(const char*); - //string(const string&); unsigned int size() const; unsigned int length() const; bool empty() const; @@ -119,7 +118,6 @@ as this is overloaded by the const char* version // assign does not return a copy of this object // (no point in a scripting language) void assign(const char*); - //void assign(const string&); // no support for all the other features // it's probably better to do it in lua }; diff --git a/Lib/lua/std_vector.i b/Lib/lua/std_vector.i index a4ea978db..9eb85e9e6 100644 --- a/Lib/lua/std_vector.i +++ b/Lib/lua/std_vector.i @@ -25,10 +25,19 @@ namespace std { template class vector { public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + vector(); vector(unsigned int); - vector(const vector&); + vector(const vector& other); vector(unsigned int,T); + unsigned int size() const; unsigned int max_size() const; bool empty() const; diff --git a/Lib/lua/typemaps.i b/Lib/lua/typemaps.i index c662cd31e..8392e5bfa 100644 --- a/Lib/lua/typemaps.i +++ b/Lib/lua/typemaps.i @@ -182,7 +182,7 @@ TYPE* SWIG_get_NAME_num_array_var(lua_State* L, int index, int* size); // writes a table to Lua with all the specified numbers void SWIG_write_NAME_num_array(lua_State* L,TYPE *array,int size); // read the specified table, and fills the array with numbers - // returns 1 of ok (only fails if it doesnt find numbers) + // returns 1 of ok (only fails if it doesn't find numbers) // helper fn (called by SWIG_get_NAME_num_array_*() fns) int SWIG_read_NAME_num_array(lua_State* L,int index,TYPE *array,int size); diff --git a/Lib/modula3/modula3.swg b/Lib/modula3/modula3.swg index 262f8ead4..13d06e9c6 100644 --- a/Lib/modula3/modula3.swg +++ b/Lib/modula3/modula3.swg @@ -782,4 +782,6 @@ FROM BlaBla IMPORT Bla; /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } diff --git a/Lib/mzscheme/mzrun.swg b/Lib/mzscheme/mzrun.swg index 06447d78d..c438c9ce8 100644 --- a/Lib/mzscheme/mzrun.swg +++ b/Lib/mzscheme/mzrun.swg @@ -158,7 +158,7 @@ SWIG_MzScheme_ConvertPtr(Scheme_Object *s, void **result, swig_type_info *type, if (SCHEME_NULLP(s)) { *result = NULL; - return 0; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } else if (SCHEME_TYPE(s) == swig_type) { struct swig_mz_proxy *proxy = (struct swig_mz_proxy *) s; if (type) { diff --git a/Lib/mzscheme/mzscheme.swg b/Lib/mzscheme/mzscheme.swg index 9ae242845..f45c87250 100644 --- a/Lib/mzscheme/mzscheme.swg +++ b/Lib/mzscheme/mzscheme.swg @@ -7,6 +7,7 @@ /* Include headers */ %runtime "swigrun.swg" // Common C API type-checking code +%runtime "swigerrors.swg" // SWIG errors %runtime "mzrun.swg" %define SWIG_APPEND_VALUE(value) diff --git a/Lib/mzscheme/std_common.i b/Lib/mzscheme/std_common.i index 1f1ae1ab7..a83e2731f 100644 --- a/Lib/mzscheme/std_common.i +++ b/Lib/mzscheme/std_common.i @@ -11,10 +11,13 @@ %{ #include -std::string swig_scm_to_string(Scheme_Object* x) { +SWIGINTERNINLINE +std::string swig_scm_to_string(Scheme_Object *x) { return std::string(SCHEME_STR_VAL(x)); } -Scheme_Object* swig_make_string(const std::string& s) { + +SWIGINTERNINLINE +Scheme_Object *swig_make_string(const std::string &s) { return scheme_make_string(s.c_str()); } %} diff --git a/Lib/mzscheme/std_map.i b/Lib/mzscheme/std_map.i index 849f8baf5..1d3eec241 100644 --- a/Lib/mzscheme/std_map.i +++ b/Lib/mzscheme/std_map.i @@ -40,12 +40,12 @@ namespace std { - template class map { - %typemap(in) map (std::map* m) { + template > class map { + %typemap(in) map< K, T, C > (std::map< K, T, C >* m) { if (SCHEME_NULLP($input)) { - $1 = std::map(); + $1 = std::map< K, T, C >(); } else if (SCHEME_PAIRP($input)) { - $1 = std::map(); + $1 = std::map< K, T, C >(); Scheme_Object* alist = $input; while (!SCHEME_NULLP(alist)) { K* k; @@ -72,15 +72,15 @@ namespace std { SWIG_MustGetPtr($input,$&1_descriptor,$argnum, 0)); } } - %typemap(in) const map& (std::map temp, - std::map* m), - const map* (std::map temp, - std::map* m) { + %typemap(in) const map< K, T, C >& (std::map< K, T, C > temp, + std::map< K, T, C >* m), + const map< K, T, C >* (std::map< K, T, C > temp, + std::map< K, T, C >* m) { if (SCHEME_NULLP($input)) { - temp = std::map(); + temp = std::map< K, T, C >(); $1 = &temp; } else if (SCHEME_PAIRP($input)) { - temp = std::map(); + temp = std::map< K, T, C >(); $1 = &temp; Scheme_Object* alist = $input; while (!SCHEME_NULLP(alist)) { @@ -107,9 +107,9 @@ namespace std { $1 = ($1_ltype) SWIG_MustGetPtr($input,$1_descriptor,$argnum, 0); } } - %typemap(out) map { + %typemap(out) map< K, T, C > { Scheme_Object* alist = scheme_null; - for (std::map::reverse_iterator i=$1.rbegin(); + for (std::map< K, T, C >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { K* key = new K(i->first); T* val = new T(i->second); @@ -120,7 +120,7 @@ namespace std { } $result = alist; } - %typecheck(SWIG_TYPECHECK_MAP) map { + %typecheck(SWIG_TYPECHECK_MAP) map< K, T, C > { /* native sequence? */ if (SCHEME_NULLP($input)) { /* an empty sequence can be of any type */ @@ -156,7 +156,7 @@ namespace std { } } else { /* wrapped map? */ - std::map* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $&1_descriptor, 0) != -1) $1 = 1; @@ -164,8 +164,8 @@ namespace std { $1 = 0; } } - %typecheck(SWIG_TYPECHECK_MAP) const map&, - const map* { + %typecheck(SWIG_TYPECHECK_MAP) const map< K, T, C >&, + const map< K, T, C >* { /* native sequence? */ if (SCHEME_NULLP($input)) { /* an empty sequence can be of any type */ @@ -201,7 +201,7 @@ namespace std { } } else { /* wrapped map? */ - std::map* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $1_descriptor, 0) != -1) $1 = 1; @@ -221,15 +221,21 @@ namespace std { typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { T& __getitem__(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -239,19 +245,19 @@ namespace std { (*self)[key] = x; } void __delitem__(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } Scheme_Object* keys() { Scheme_Object* result = scheme_null; - for (std::map::reverse_iterator i=self->rbegin(); + for (std::map< K, T, C >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { K* key = new K(i->first); Scheme_Object* k = SWIG_NewPointerObj(key,$descriptor(K *), 1); @@ -267,12 +273,12 @@ namespace std { %define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) - template class map { - %typemap(in) map (std::map* m) { + template class map< K, T, C > { + %typemap(in) map< K, T, C > (std::map< K, T, C >* m) { if (SCHEME_NULLP($input)) { - $1 = std::map(); + $1 = std::map< K, T, C >(); } else if (SCHEME_PAIRP($input)) { - $1 = std::map(); + $1 = std::map< K, T, C >(); Scheme_Object* alist = $input; while (!SCHEME_NULLP(alist)) { T* x; @@ -284,7 +290,7 @@ namespace std { val = scheme_cdr(entry); if (!CHECK(key)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); if (SWIG_ConvertPtr(val,(void**) &x, $descriptor(T *), 0) == -1) { if (!SCHEME_PAIRP(val)) @@ -300,15 +306,15 @@ namespace std { SWIG_MustGetPtr($input,$&1_descriptor,$argnum, 0)); } } - %typemap(in) const map& (std::map temp, - std::map* m), - const map* (std::map temp, - std::map* m) { + %typemap(in) const map< K, T, C >& (std::map< K, T, C > temp, + std::map< K, T, C >* m), + const map< K, T, C >* (std::map< K, T, C > temp, + std::map< K, T, C >* m) { if (SCHEME_NULLP($input)) { - temp = std::map(); + temp = std::map< K, T, C >(); $1 = &temp; } else if (SCHEME_PAIRP($input)) { - temp = std::map(); + temp = std::map< K, T, C >(); $1 = &temp; Scheme_Object* alist = $input; while (!SCHEME_NULLP(alist)) { @@ -321,7 +327,7 @@ namespace std { val = scheme_cdr(entry); if (!CHECK(key)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); if (SWIG_ConvertPtr(val,(void**) &x, $descriptor(T *), 0) == -1) { if (!SCHEME_PAIRP(val)) @@ -336,9 +342,9 @@ namespace std { $1 = ($1_ltype) SWIG_MustGetPtr($input,$1_descriptor,$argnum, 0); } } - %typemap(out) map { + %typemap(out) map< K, T, C > { Scheme_Object* alist = scheme_null; - for (std::map::reverse_iterator i=$1.rbegin(); + for (std::map< K, T, C >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { T* val = new T(i->second); Scheme_Object* k = CONVERT_TO(i->first); @@ -348,7 +354,7 @@ namespace std { } $result = alist; } - %typecheck(SWIG_TYPECHECK_MAP) map { + %typecheck(SWIG_TYPECHECK_MAP) map< K, T, C > { // native sequence? if (SCHEME_NULLP($input)) { /* an empty sequence can be of any type */ @@ -382,7 +388,7 @@ namespace std { } } else { // wrapped map? - std::map* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $&1_descriptor, 0) != -1) $1 = 1; @@ -390,8 +396,8 @@ namespace std { $1 = 0; } } - %typecheck(SWIG_TYPECHECK_MAP) const map&, - const map* { + %typecheck(SWIG_TYPECHECK_MAP) const map< K, T, C >&, + const map< K, T, C >* { // native sequence? if (SCHEME_NULLP($input)) { /* an empty sequence can be of any type */ @@ -425,7 +431,7 @@ namespace std { } } else { // wrapped map? - std::map* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $1_descriptor, 0) != -1) $1 = 1; @@ -441,15 +447,25 @@ namespace std { %rename("delete!") __delitem__; %rename("has-key?") has_key; public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { T& __getitem__(K key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -459,19 +475,19 @@ namespace std { (*self)[key] = x; } void __delitem__(K key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(K key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } Scheme_Object* keys() { Scheme_Object* result = scheme_null; - for (std::map::reverse_iterator i=self->rbegin(); + for (std::map< K, T, C >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { Scheme_Object* k = CONVERT_TO(i->first); result = scheme_make_pair(k,result); @@ -483,12 +499,12 @@ namespace std { %enddef %define specialize_std_map_on_value(T,CHECK,CONVERT_FROM,CONVERT_TO) - template class map { - %typemap(in) map (std::map* m) { + template class map< K, T, C > { + %typemap(in) map< K, T, C > (std::map< K, T, C >* m) { if (SCHEME_NULLP($input)) { - $1 = std::map(); + $1 = std::map< K, T, C >(); } else if (SCHEME_PAIRP($input)) { - $1 = std::map(); + $1 = std::map< K, T, C >(); Scheme_Object* alist = $input; while (!SCHEME_NULLP(alist)) { K* k; @@ -505,7 +521,7 @@ namespace std { val = scheme_car(val); if (!CHECK(val)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); } (($1_type &)$1)[*k] = CONVERT_FROM(val); alist = scheme_cdr(alist); @@ -515,15 +531,15 @@ namespace std { SWIG_MustGetPtr($input,$&1_descriptor,$argnum, 0)); } } - %typemap(in) const map& (std::map temp, - std::map* m), - const map* (std::map temp, - std::map* m) { + %typemap(in) const map< K, T, C >& (std::map< K, T, C > temp, + std::map< K, T, C >* m), + const map< K, T, C >* (std::map< K, T, C > temp, + std::map< K, T, C >* m) { if (SCHEME_NULLP($input)) { - temp = std::map(); + temp = std::map< K, T, C >(); $1 = &temp; } else if (SCHEME_PAIRP($input)) { - temp = std::map(); + temp = std::map< K, T, C >(); $1 = &temp; Scheme_Object* alist = $input; while (!SCHEME_NULLP(alist)) { @@ -541,7 +557,7 @@ namespace std { val = scheme_car(val); if (!CHECK(val)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); } temp[*k] = CONVERT_FROM(val); alist = scheme_cdr(alist); @@ -550,9 +566,9 @@ namespace std { $1 = ($1_ltype) SWIG_MustGetPtr($input,$1_descriptor,$argnum, 0); } } - %typemap(out) map { + %typemap(out) map< K, T, C > { Scheme_Object* alist = scheme_null; - for (std::map::reverse_iterator i=$1.rbegin(); + for (std::map< K, T, C >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { K* key = new K(i->first); Scheme_Object* k = SWIG_NewPointerObj(key,$descriptor(K *), 1); @@ -562,7 +578,7 @@ namespace std { } $result = alist; } - %typecheck(SWIG_TYPECHECK_MAP) map { + %typecheck(SWIG_TYPECHECK_MAP) map< K, T, C > { // native sequence? if (SCHEME_NULLP($input)) { /* an empty sequence can be of any type */ @@ -595,7 +611,7 @@ namespace std { } } else { // wrapped map? - std::map* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $&1_descriptor, 0) != -1) $1 = 1; @@ -603,8 +619,8 @@ namespace std { $1 = 0; } } - %typecheck(SWIG_TYPECHECK_MAP) const map&, - const map* { + %typecheck(SWIG_TYPECHECK_MAP) const map< K, T, C >&, + const map< K, T, C >* { // native sequence? if (SCHEME_NULLP($input)) { /* an empty sequence can be of any type */ @@ -637,7 +653,7 @@ namespace std { } } else { // wrapped map? - std::map* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $1_descriptor, 0) != -1) $1 = 1; @@ -653,15 +669,25 @@ namespace std { %rename("delete!") __delitem__; %rename("has-key?") has_key; public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { T __getitem__(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -671,19 +697,19 @@ namespace std { (*self)[key] = x; } void __delitem__(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } Scheme_Object* keys() { Scheme_Object* result = scheme_null; - for (std::map::reverse_iterator i=self->rbegin(); + for (std::map< K, T, C >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { K* key = new K(i->first); Scheme_Object* k = SWIG_NewPointerObj(key,$descriptor(K *), 1); @@ -697,12 +723,12 @@ namespace std { %define specialize_std_map_on_both(K,CHECK_K,CONVERT_K_FROM,CONVERT_K_TO, T,CHECK_T,CONVERT_T_FROM,CONVERT_T_TO) - template<> class map { - %typemap(in) map (std::map* m) { + template<> class map< K, T, C > { + %typemap(in) map< K, T, C > (std::map< K, T, C >* m) { if (SCHEME_NULLP($input)) { - $1 = std::map(); + $1 = std::map< K, T, C >(); } else if (SCHEME_PAIRP($input)) { - $1 = std::map(); + $1 = std::map< K, T, C >(); Scheme_Object* alist = $input; while (!SCHEME_NULLP(alist)) { Scheme_Object *entry, *key, *val; @@ -713,14 +739,14 @@ namespace std { val = scheme_cdr(entry); if (!CHECK_K(key)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); if (!CHECK_T(val)) { if (!SCHEME_PAIRP(val)) SWIG_exception(SWIG_TypeError,"alist expected"); val = scheme_car(val); if (!CHECK_T(val)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); } (($1_type &)$1)[CONVERT_K_FROM(key)] = CONVERT_T_FROM(val); @@ -731,15 +757,15 @@ namespace std { SWIG_MustGetPtr($input,$&1_descriptor,$argnum, 0)); } } - %typemap(in) const map& (std::map temp, - std::map* m), - const map* (std::map temp, - std::map* m) { + %typemap(in) const map< K, T, C >& (std::map< K, T, C > temp, + std::map< K, T, C >* m), + const map< K, T, C >* (std::map< K, T, C > temp, + std::map< K, T, C >* m) { if (SCHEME_NULLP($input)) { - temp = std::map(); + temp = std::map< K, T, C >(); $1 = &temp; } else if (SCHEME_PAIRP($input)) { - temp = std::map(); + temp = std::map< K, T, C >(); $1 = &temp; Scheme_Object* alist = $input; while (!SCHEME_NULLP(alist)) { @@ -751,14 +777,14 @@ namespace std { val = scheme_cdr(entry); if (!CHECK_K(key)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); if (!CHECK_T(val)) { if (!SCHEME_PAIRP(val)) SWIG_exception(SWIG_TypeError,"alist expected"); val = scheme_car(val); if (!CHECK_T(val)) SWIG_exception(SWIG_TypeError, - "map<" #K "," #T "> expected"); + "map<" #K "," #T "," #C "> expected"); } temp[CONVERT_K_FROM(key)] = CONVERT_T_FROM(val); alist = scheme_cdr(alist); @@ -767,9 +793,9 @@ namespace std { $1 = ($1_ltype) SWIG_MustGetPtr($input,$1_descriptor,$argnum, 0); } } - %typemap(out) map { + %typemap(out) map< K, T, C > { Scheme_Object* alist = scheme_null; - for (std::map::reverse_iterator i=$1.rbegin(); + for (std::map< K, T, C >::reverse_iterator i=$1.rbegin(); i!=$1.rend(); ++i) { Scheme_Object* k = CONVERT_K_TO(i->first); Scheme_Object* x = CONVERT_T_TO(i->second); @@ -778,7 +804,7 @@ namespace std { } $result = alist; } - %typecheck(SWIG_TYPECHECK_MAP) map { + %typecheck(SWIG_TYPECHECK_MAP) map< K, T, C > { // native sequence? if (SCHEME_NULLP($input)) { /* an empty sequence can be of any type */ @@ -809,7 +835,7 @@ namespace std { } } else { // wrapped map? - std::map* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $&1_descriptor, 0) != -1) $1 = 1; @@ -817,8 +843,8 @@ namespace std { $1 = 0; } } - %typecheck(SWIG_TYPECHECK_MAP) const map&, - const map* { + %typecheck(SWIG_TYPECHECK_MAP) const map< K, T, C >&, + const map< K, T, C >* { // native sequence? if (SCHEME_NULLP($input)) { /* an empty sequence can be of any type */ @@ -849,7 +875,7 @@ namespace std { } } else { // wrapped map? - std::map* m; + std::map< K, T, C >* m; if (SWIG_ConvertPtr($input,(void **) &m, $1_descriptor, 0) != -1) $1 = 1; @@ -865,15 +891,25 @@ namespace std { %rename("delete!") __delitem__; %rename("has-key?") has_key; public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { T __getitem__(K key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -883,19 +919,19 @@ namespace std { (*self)[key] = x; } void __delitem__(K key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(K key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } Scheme_Object* keys() { Scheme_Object* result = scheme_null; - for (std::map::reverse_iterator i=self->rbegin(); + for (std::map< K, T, C >::reverse_iterator i=self->rbegin(); i!=self->rend(); ++i) { Scheme_Object* k = CONVERT_K_TO(i->first); result = scheme_make_pair(k,result); diff --git a/Lib/mzscheme/std_pair.i b/Lib/mzscheme/std_pair.i index d5a65470d..75f6751cc 100644 --- a/Lib/mzscheme/std_pair.i +++ b/Lib/mzscheme/std_pair.i @@ -115,11 +115,15 @@ namespace std { $1 = 0; } } + + typedef T first_type; + typedef U second_type; + pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; @@ -219,9 +223,9 @@ namespace std { } pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; @@ -320,9 +324,9 @@ namespace std { } pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; @@ -415,9 +419,9 @@ namespace std { } pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/mzscheme/std_vector.i b/Lib/mzscheme/std_vector.i index 22e1fa96b..0ef5edb15 100644 --- a/Lib/mzscheme/std_vector.i +++ b/Lib/mzscheme/std_vector.i @@ -189,9 +189,18 @@ namespace std { } } public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + vector(unsigned int size = 0); vector(unsigned int size, const T& value); - vector(const vector&); + vector(const vector& other); + %rename(length) size; unsigned int size() const; %rename("empty?") empty; @@ -365,9 +374,18 @@ namespace std { } } public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + vector(unsigned int size = 0); vector(unsigned int size, const T& value); - vector(const vector&); + vector(const vector& other); + %rename(length) size; unsigned int size() const; %rename("empty?") empty; diff --git a/Lib/mzscheme/stl.i b/Lib/mzscheme/stl.i index b19eae58b..04f86014f 100644 --- a/Lib/mzscheme/stl.i +++ b/Lib/mzscheme/stl.i @@ -1,8 +1,7 @@ /* ----------------------------------------------------------------------------- * stl.i - * - * Initial STL definition. extended as needed in each language * ----------------------------------------------------------------------------- */ + %include %include %include diff --git a/Lib/mzscheme/typemaps.i b/Lib/mzscheme/typemaps.i index 9346349bd..09bda2cca 100644 --- a/Lib/mzscheme/typemaps.i +++ b/Lib/mzscheme/typemaps.i @@ -329,7 +329,7 @@ REF_MAP(double, SCHEME_REALP, scheme_real_to_double, $1 = (SCHEME_STRINGP($input)) ? 1 : 0; } -%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] { +%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE [] { void *ptr; if (SWIG_ConvertPtr($input, (void **) &ptr, $1_descriptor, 0)) { $1 = 0; @@ -338,9 +338,18 @@ REF_MAP(double, SCHEME_REALP, scheme_real_to_double, } } +%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE &, SWIGTYPE && { + void *ptr; + if (SWIG_ConvertPtr($input, (void **) &ptr, $1_descriptor, SWIG_POINTER_NO_NULL)) { + $1 = 0; + } else { + $1 = 1; + } +} + %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { void *ptr; - if (SWIG_ConvertPtr($input, (void **) &ptr, $&1_descriptor, 0)) { + if (SWIG_ConvertPtr($input, (void **) &ptr, $&1_descriptor, SWIG_POINTER_NO_NULL)) { $1 = 0; } else { $1 = 1; diff --git a/Lib/ocaml/carray.i b/Lib/ocaml/carray.i index bbf1ddd58..5e74c3da1 100644 --- a/Lib/ocaml/carray.i +++ b/Lib/ocaml/carray.i @@ -9,7 +9,6 @@ type _value = c_obj %define %array_tmap_out(type,what,out_f) %typemap(type) what [ANY] { int i; - /* $*1_type */ $result = caml_array_new($1_dim0); for( i = 0; i < $1_dim0; i++ ) { caml_array_set($result,i,out_f($1[i])); @@ -20,7 +19,6 @@ type _value = c_obj %define %array_tmap_in(type,what,in_f) %typemap(type) what [ANY] { int i; - /* $*1_type */ $1 = ($*1_type *)malloc( $1_size ); for( i = 0; i < $1_dim0 && i < caml_array_len($input); i++ ) { $1[i] = in_f(caml_array_nth($input,i)); @@ -57,7 +55,6 @@ type _value = c_obj %typemap(in) SWIGTYPE [] { int i; - /* $*1_type */ $1 = new $*1_type [$1_dim0]; for( i = 0; i < $1_dim0 && i < caml_array_len($input); i++ ) { $1[i] = *(($*1_ltype *) @@ -69,7 +66,6 @@ type _value = c_obj %typemap(in) SWIGTYPE [] { int i; - /* $*1_type */ $1 = ($*1_type *)malloc( $1_size ); for( i = 0; i < $1_dim0 && i < caml_array_len($input); i++ ) { $1[i] = *(($*1_ltype) @@ -89,7 +85,7 @@ type _value = c_obj caml_array_set ($result, i, - callback(*fromval,caml_val_ptr((void *)&$1[i],$*1_descriptor))); + caml_callback(*fromval,caml_val_ptr((void *)&$1[i],$*1_descriptor))); } else { caml_array_set ($result, @@ -102,7 +98,6 @@ type _value = c_obj %typemap(in) enum SWIGTYPE [] { int i; - /* $*1_type */ $1 = ($*1_type *)malloc( $1_size ); for( i = 0; i < $1_dim0 && i < caml_array_len($input); i++ ) { $1[i] = ($type) @@ -119,7 +114,7 @@ type _value = c_obj caml_array_set ($result, i, - callback2(*caml_named_value(SWIG_MODULE "_int_to_enum"), + caml_callback2(*caml_named_value(SWIG_MODULE "_int_to_enum"), *caml_named_value("$type_marker"), Val_int($1[i]))); } diff --git a/Lib/ocaml/class.swg b/Lib/ocaml/class.swg index 0ee304cab..eb369cd70 100644 --- a/Lib/ocaml/class.swg +++ b/Lib/ocaml/class.swg @@ -56,6 +56,7 @@ begin (fun mth arg -> invoke_inner raw_ptr mth arg) end +let _ = register_class_byname "$realname" create_$classname_from_ptr let _ = Callback.register "create_$normalized_from_ptr" create_$classname_from_ptr diff --git a/Lib/ocaml/cstring.i b/Lib/ocaml/cstring.i index 0d6aa4b69..f1190ad5c 100644 --- a/Lib/ocaml/cstring.i +++ b/Lib/ocaml/cstring.i @@ -108,7 +108,7 @@ %define %cstring_mutable(TYPEMAP,...) %typemap(in) TYPEMAP { char *t = String_val($input); - int n = string_length($input); + int n = caml_string_length($input); $1 = ($1_ltype) t; #if #__VA_ARGS__ == "" #ifdef __cplusplus diff --git a/Lib/ocaml/director.swg b/Lib/ocaml/director.swg index 158cbfeec..eb91aaf4b 100644 --- a/Lib/ocaml/director.swg +++ b/Lib/ocaml/director.swg @@ -74,12 +74,12 @@ namespace Swig { public: /* wrap a ocaml object. */ Director(CAML_VALUE self) : swig_self(self), swig_disown_flag(false) { - register_global_root(&swig_self); + caml_register_global_root(&swig_self); } /* discard our reference at destruction */ virtual ~Director() { - remove_global_root(&swig_self); + caml_remove_global_root(&swig_self); swig_disown(); // Disown is safe here because we're just divorcing a reference that points to us. } @@ -93,7 +93,7 @@ namespace Swig { void swig_disown() const { if (!swig_disown_flag) { swig_disown_flag=true; - callback(*caml_named_value("caml_obj_disown"),swig_self); + caml_callback(*caml_named_value("caml_obj_disown"),swig_self); } } }; diff --git a/Lib/ocaml/extra-install.list b/Lib/ocaml/extra-install.list index a63c7fc2f..16486eb2c 100644 --- a/Lib/ocaml/extra-install.list +++ b/Lib/ocaml/extra-install.list @@ -1,5 +1,4 @@ # see top-level Makefile.in -# libswigocaml is not needed anymore. swigp4.ml swig.mli swig.ml diff --git a/Lib/ocaml/libswigocaml.h b/Lib/ocaml/libswigocaml.h deleted file mode 100644 index e752540fe..000000000 --- a/Lib/ocaml/libswigocaml.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Ocaml runtime support */ - -#ifdef __cplusplus -extern "C" { -#endif - - typedef int oc_bool; - extern void *nullptr; - - extern oc_bool isnull( void *v ); - - extern void *get_char_ptr( char *str ); - extern void *make_ptr_array( int size ); - extern void *get_ptr( void *arrayptr, int elt ); - extern void set_ptr( void *arrayptr, int elt, void *elt_v ); - extern void *offset_ptr( void *ptr, int n ); - -#ifdef __cplusplus -}; -#endif diff --git a/Lib/ocaml/ocaml.i b/Lib/ocaml/ocaml.i index e099f7c10..cc26d1859 100644 --- a/Lib/ocaml/ocaml.i +++ b/Lib/ocaml/ocaml.i @@ -4,15 +4,11 @@ * SWIG Configuration File for Ocaml * ----------------------------------------------------------------------------- */ -%runtime %{ -#define SWIGSTATIC static -%} - /* Insert common stuff */ %insert(runtime) "swigrun.swg" /* Include headers */ -%insert(runtime) "ocamldec.swg" +%insert(runtime) "ocamlrundec.swg" /* Type registration */ %insert(init) "swiginit.swg" @@ -32,18 +28,14 @@ %} /*#ifndef SWIG_NOINCLUDE*/ -%insert(runtime) "ocaml.swg" +%insert(runtime) "ocamlrun.swg" /*#endif*/ %insert(classtemplate) "class.swg" -/* Definitions */ -#define SWIG_malloc(size) swig_malloc(size, FUNC_NAME) -#define SWIG_free(mem) free(mem) - /* Read in standard typemaps. */ %include -%include +%include %include %include %include diff --git a/Lib/ocaml/ocaml.swg b/Lib/ocaml/ocaml.swg index a00252b28..ac496bdba 100644 --- a/Lib/ocaml/ocaml.swg +++ b/Lib/ocaml/ocaml.swg @@ -1,602 +1,311 @@ -/* -*-c-*- */ +/* ----------------------------------------------------------------------------- + * ocaml.swg + * + * The Ocaml module handles all types uniformly via typemaps. Here + * are the definitions. + * ----------------------------------------------------------------------------- */ -/* SWIG pointer structure */ +/* Pointers */ -#include -#include +%typemap(in) void "" -#ifdef __cplusplus -extern "C" { -#endif +%typemap(out) void "$result = Val_int(0);" -#define C_bool 0 -#define C_char 1 -#define C_uchar 2 -#define C_short 3 -#define C_ushort 4 -#define C_int 5 -#define C_uint 6 -#define C_int32 7 -#define C_int64 8 -#define C_float 9 -#define C_double 10 -#define C_ptr 11 -#define C_array 12 -#define C_list 13 -#define C_obj 14 -#define C_string 15 -#define C_enum 16 -#define C_director_core 17 +%typemap(in) void * { + $1 = caml_ptr_val($input,$descriptor); +} +%typemap(varin) void * { + $1 = ($ltype)caml_ptr_val($input,$descriptor); +} -/* Cast a pointer if possible; returns 1 if successful */ - - SWIGSTATIC int - SWIG_Cast (void *source, swig_type_info *source_type, - void **ptr, swig_type_info *dest_type) - { - if( !source ) { // Special case for NULL. This is a popular question - // for other modules on the list, so I want an easy way out... - *ptr = 0; - return 0; - } +%typemap(out) void * { + $result = caml_val_ptr($1,$descriptor); +} -#ifdef TYPE_CAST_VERBOSE - fprintf( stderr, "Trying to cast %s to %s\n", - source_type ? source_type->str : "", - dest_type ? dest_type->str : "" ); -#endif - if (dest_type != source_type) { - /* We have a type mismatch. Will have to look through our type - mapping table to figure out whether or not we can accept this - datatype. - -- - Ignore typechecks for void *. Allow any conversion. */ - if( !dest_type || !source_type || - !strcmp(dest_type->name,"_p_void") || - !strcmp(source_type->name,"_p_void") ) { - *ptr = source; - return 0; - } else { - swig_cast_info *tc = - SWIG_TypeCheckStruct(source_type, dest_type ); -#ifdef TYPE_CAST_VERBOSE - fprintf( stderr, "Typecheck -> %s\n", - tc ? tc->str : "" ); -#endif - if( tc ) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc, source, &newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - return 0; - } else - return -1; - } - } else { - *ptr = source; - return 0; - } +%typemap(varout) void * { + $result = caml_val_ptr($1,$descriptor); +} + +%typemap(in) char *& (char *temp) { + temp = (char*)caml_val_ptr($1,$descriptor); + $1 = &temp; +} + +%typemap(argout) char *& { + swig_result = caml_list_append(swig_result,caml_val_string_len(*$1, strlen(*$1))); +} + +%typemap(in) SWIGTYPE & { + $1 = ($ltype) caml_ptr_val($input,$1_descriptor); +} + +%typemap(in) SWIGTYPE && { + $1 = ($ltype) caml_ptr_val($input,$1_descriptor); +} + +%typemap(varin) SWIGTYPE & { + $1 = *(($ltype) caml_ptr_val($input,$1_descriptor)); +} + +%typemap(varin) SWIGTYPE && { + $1 = *(($ltype) caml_ptr_val($input,$1_descriptor)); +} + +%typemap(varout) SWIGTYPE &, SWIGTYPE && { + $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)&$1, $1_descriptor); +} + +%typemap(out) SWIGTYPE &, SWIGTYPE && { + $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)$1, $1_descriptor); +} + +#if 0 +%typemap(argout) SWIGTYPE & { + CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); + if( fromval ) { + swig_result = + caml_list_append(swig_result, + caml_callback(*fromval,caml_val_ptr((void *) $1, + $1_descriptor))); + } else { + swig_result = + caml_list_append(swig_result, + caml_val_ptr ((void *) $1,$1_descriptor)); } - -/* Return 0 if successful. */ - SWIGSTATIC int - SWIG_GetPtr(void *inptr, void **outptr, - swig_type_info *intype, swig_type_info *outtype) { - if (intype) { - return SWIG_Cast(inptr, intype, - outptr, outtype) == -1; - } else { - *outptr = inptr; - return 0; - } +} +%typemap(argout) SWIGTYPE && { + CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); + if( fromval ) { + swig_result = + caml_list_append(swig_result, + caml_callback(*fromval,caml_val_ptr((void *) $1, + $1_descriptor))); + } else { + swig_result = + caml_list_append(swig_result, + caml_val_ptr ((void *) $1,$1_descriptor)); } - - SWIGSTATIC void caml_print_list( CAML_VALUE v ); - - SWIGSTATIC void caml_print_val( CAML_VALUE v ) { - switch( SWIG_Tag_val(v) ) { - case C_bool: - if( Bool_val(SWIG_Field(v,0)) ) fprintf( stderr, "true " ); - else fprintf( stderr, "false " ); - break; - case C_char: - case C_uchar: - fprintf( stderr, "'%c' (\\%03d) ", - (Int_val(SWIG_Field(v,0)) >= ' ' && - Int_val(SWIG_Field(v,0)) < 127) ? Int_val(SWIG_Field(v,0)) : '.', - Int_val(SWIG_Field(v,0)) ); - break; - case C_short: - case C_ushort: - case C_int: - fprintf( stderr, "%d ", (int)caml_long_val(v) ); - break; - - case C_uint: - case C_int32: - fprintf( stderr, "%ud ", (unsigned int)caml_long_val(v) ); - break; - case C_int64: - fprintf( stderr, "%ld ", caml_long_val(v) ); - break; - case C_float: - case C_double: - fprintf( stderr, "%f ", caml_double_val(v) ); - break; - - case C_ptr: - { - void *vout = 0; - swig_type_info *ty = (swig_type_info *)(long)SWIG_Int64_val(SWIG_Field(v,1)); - caml_ptr_val_internal(v,&vout,0); - fprintf( stderr, "PTR(%p,%s) ", - vout, - ty ? ty->name : "(null)" ); - } - break; - case C_array: - { - unsigned int i; - for( i = 0; i < Wosize_val( SWIG_Field(v,0) ); i++ ) - caml_print_val( SWIG_Field(SWIG_Field(v,0),i) ); - } - break; - case C_list: - caml_print_list( SWIG_Field(v,0) ); - break; - case C_obj: - fprintf( stderr, "OBJ(%p) ", (void *)SWIG_Field(v,0) ); - break; - case C_string: - { - void *cout; - caml_ptr_val_internal(v,&cout,0); - fprintf( stderr, "'%s' ", (char *)cout ); - } - break; - } - } - - SWIGSTATIC void caml_print_list( CAML_VALUE v ) { - CAMLparam1(v); - while( v && Is_block(v) ) { - fprintf( stderr, "[ " ); - caml_print_val( SWIG_Field(v,0) ); - fprintf( stderr, "]\n" ); - v = SWIG_Field(v,1); - } - CAMLreturn0; - } - - SWIGSTATIC CAML_VALUE caml_list_nth( CAML_VALUE lst, int n ) { - CAMLparam1(lst); - int i = 0; - while( i < n && lst && Is_block(lst) ) { - i++; lst = SWIG_Field(lst,1); - } - if( lst == Val_unit ) CAMLreturn(Val_unit); - else CAMLreturn(SWIG_Field(lst,0)); - } - - SWIGSTATIC CAML_VALUE caml_list_append( CAML_VALUE lst, CAML_VALUE elt ) { - CAMLparam2(lst,elt); - SWIG_CAMLlocal3(v,vt,lh); - lh = Val_unit; - v = Val_unit; - - /* Appending C_void should have no effect */ - if( !Is_block(elt) ) return lst; - - while( lst && Is_block(lst) ) { - if( v && v != Val_unit ) { - vt = alloc_tuple(2); - SWIG_Store_field(v,1,vt); - v = vt; - } else { - v = lh = alloc_tuple(2); - } - SWIG_Store_field(v,0,SWIG_Field(lst,0)); - lst = SWIG_Field(lst,1); - } - - if( v && Is_block(v) ) { - vt = alloc_tuple(2); - SWIG_Store_field(v,1,vt); - v = vt; - } else { - v = lh = alloc_tuple(2); - } - SWIG_Store_field(v,0,elt); - SWIG_Store_field(v,1,Val_unit); - - CAMLreturn(lh); - } - - SWIGSTATIC int caml_list_length( CAML_VALUE lst ) { - CAMLparam1(lst); - int i = 0; - while( lst && Is_block(lst) ) { i++; lst = SWIG_Field(lst,1); } - CAMLreturn(i); - } - - SWIGSTATIC void caml_array_set( CAML_VALUE arr, int n, CAML_VALUE item ) { - CAMLparam2(arr,item); - SWIG_Store_field(SWIG_Field(arr,0),n,item); - CAMLreturn0; - } - - SWIGSTATIC value caml_array_nth( CAML_VALUE arr, int n ) { - CAMLparam1(arr); - if( SWIG_Tag_val(arr) == C_array ) - CAMLreturn(SWIG_Field(SWIG_Field(arr,0),n)); - else if( SWIG_Tag_val(arr) == C_list ) - CAMLreturn(caml_list_nth(arr,0)); - else - failwith("Need array or list"); - } - - SWIGSTATIC int caml_array_len( CAML_VALUE arr ) { - CAMLparam1(arr); - if( SWIG_Tag_val(arr) == C_array ) - CAMLreturn(Wosize_val(SWIG_Field(arr,0))); - else if( SWIG_Tag_val(arr) == C_list ) - CAMLreturn(caml_list_length(arr)); - else - failwith("Need array or list"); - } - - SWIGSTATIC CAML_VALUE caml_swig_alloc(int x,int y) { - return caml_alloc(x,y); - } - - SWIGSTATIC value caml_array_new( int n ) { - CAMLparam0(); - SWIG_CAMLlocal1(vv); - vv = caml_swig_alloc(1,C_array); - SWIG_Store_field(vv,0,alloc_tuple(n)); - CAMLreturn(vv); - } - - SWIGSTATIC CAML_VALUE caml_val_bool( int b ) { - CAMLparam0(); - SWIG_CAMLlocal1(bv); - bv = caml_swig_alloc(1,C_bool); - SWIG_Store_field(bv,0,Val_bool(b)); - CAMLreturn(bv); - } - - SWIGSTATIC CAML_VALUE caml_val_char( char c ) { - CAMLparam0(); - SWIG_CAMLlocal1(cv); - cv = caml_swig_alloc(1,C_char); - SWIG_Store_field(cv,0,Val_int(c)); - CAMLreturn(cv); - } - - SWIGSTATIC CAML_VALUE caml_val_uchar( unsigned char uc ) { - CAMLparam0(); - SWIG_CAMLlocal1(ucv); - ucv = caml_swig_alloc(1,C_uchar); - SWIG_Store_field(ucv,0,Val_int(uc)); - CAMLreturn(ucv); - } - - SWIGSTATIC CAML_VALUE caml_val_short( short s ) { - CAMLparam0(); - SWIG_CAMLlocal1(sv); - sv = caml_swig_alloc(1,C_short); - SWIG_Store_field(sv,0,Val_int(s)); - CAMLreturn(sv); - } - - SWIGSTATIC CAML_VALUE caml_val_ushort( unsigned short us ) { - CAMLparam0(); - SWIG_CAMLlocal1(usv); - usv = caml_swig_alloc(1,C_ushort); - SWIG_Store_field(usv,0,Val_int(us)); - CAMLreturn(usv); - } - - SWIGSTATIC CAML_VALUE caml_val_int( int i ) { - CAMLparam0(); - SWIG_CAMLlocal1(iv); - iv = caml_swig_alloc(1,C_int); - SWIG_Store_field(iv,0,Val_int(i)); - CAMLreturn(iv); - } - - SWIGSTATIC CAML_VALUE caml_val_uint( unsigned int ui ) { - CAMLparam0(); - SWIG_CAMLlocal1(uiv); - uiv = caml_swig_alloc(1,C_int); - SWIG_Store_field(uiv,0,Val_int(ui)); - CAMLreturn(uiv); - } - - SWIGSTATIC CAML_VALUE caml_val_long( long l ) { - CAMLparam0(); - SWIG_CAMLlocal1(lv); - lv = caml_swig_alloc(1,C_int64); - SWIG_Store_field(lv,0,copy_int64(l)); - CAMLreturn(lv); - } - - SWIGSTATIC CAML_VALUE caml_val_ulong( unsigned long ul ) { - CAMLparam0(); - SWIG_CAMLlocal1(ulv); - ulv = caml_swig_alloc(1,C_int64); - SWIG_Store_field(ulv,0,copy_int64(ul)); - CAMLreturn(ulv); - } - - SWIGSTATIC CAML_VALUE caml_val_float( float f ) { - CAMLparam0(); - SWIG_CAMLlocal1(fv); - fv = caml_swig_alloc(1,C_float); - SWIG_Store_field(fv,0,copy_double((double)f)); - CAMLreturn(fv); - } - - SWIGSTATIC CAML_VALUE caml_val_double( double d ) { - CAMLparam0(); - SWIG_CAMLlocal1(fv); - fv = caml_swig_alloc(1,C_double); - SWIG_Store_field(fv,0,copy_double(d)); - CAMLreturn(fv); - } - - SWIGSTATIC CAML_VALUE caml_val_ptr( void *p, swig_type_info *info ) { - CAMLparam0(); - SWIG_CAMLlocal1(vv); - vv = caml_swig_alloc(2,C_ptr); - SWIG_Store_field(vv,0,copy_int64((long)p)); - SWIG_Store_field(vv,1,copy_int64((long)info)); - CAMLreturn(vv); - } - - SWIGSTATIC CAML_VALUE caml_val_string( const char *p ) { - CAMLparam0(); - SWIG_CAMLlocal1(vv); - if( !p ) CAMLreturn(caml_val_ptr( (void *)p, 0 )); - vv = caml_swig_alloc(1,C_string); - SWIG_Store_field(vv,0,copy_string(p)); - CAMLreturn(vv); - } - - SWIGSTATIC CAML_VALUE caml_val_string_len( const char *p, int len ) { - CAMLparam0(); - SWIG_CAMLlocal1(vv); - if( !p || len < 0 ) CAMLreturn(caml_val_ptr( (void *)p, 0 )); - vv = caml_swig_alloc(1,C_string); - SWIG_Store_field(vv,0,alloc_string(len)); - memcpy(String_val(SWIG_Field(vv,0)),p,len); - CAMLreturn(vv); - } - - #define caml_val_obj(v, name) caml_val_obj_helper(v, SWIG_TypeQuery((name)), name) - SWIGSTATIC CAML_VALUE caml_val_obj_helper( void *v, swig_type_info *type, char *name) { - CAMLparam0(); - CAMLreturn(callback2(*caml_named_value("caml_create_object_fn"), - caml_val_ptr(v,type), - copy_string(name))); - } - - SWIGSTATIC long caml_long_val_full( CAML_VALUE v, char *name ) { - CAMLparam1(v); - if( !Is_block(v) ) return 0; - - switch( SWIG_Tag_val(v) ) { - case C_bool: - case C_char: - case C_uchar: - case C_short: - case C_ushort: - case C_int: - CAMLreturn(Int_val(SWIG_Field(v,0))); - case C_uint: - case C_int32: - CAMLreturn(Int32_val(SWIG_Field(v,0))); - case C_int64: - CAMLreturn((long)SWIG_Int64_val(SWIG_Field(v,0))); - case C_float: - case C_double: - CAMLreturn((long)Double_val(SWIG_Field(v,0))); - case C_string: - CAMLreturn((long)String_val(SWIG_Field(v,0))); - case C_ptr: - CAMLreturn((long)SWIG_Int64_val(SWIG_Field(SWIG_Field(v,0),0))); - case C_enum: { - SWIG_CAMLlocal1(ret); - CAML_VALUE *enum_to_int = caml_named_value(SWIG_MODULE "_enum_to_int"); - if( !name ) failwith( "Not an enum conversion" ); - ret = callback2(*enum_to_int,*caml_named_value(name),v); - CAMLreturn(caml_long_val(ret)); - } - default: - failwith("No conversion to int"); - } - } - - SWIGSTATIC long caml_long_val( CAML_VALUE v ) { - return caml_long_val_full(v,0); - } - - SWIGSTATIC double caml_double_val( CAML_VALUE v ) { - CAMLparam1(v); - if( !Is_block(v) ) return 0.0; - switch( SWIG_Tag_val(v) ) { - case C_bool: - case C_char: - case C_uchar: - case C_short: - case C_ushort: - case C_int: - CAMLreturn_type(Int_val(SWIG_Field(v,0))); - case C_uint: - case C_int32: - CAMLreturn_type(Int32_val(SWIG_Field(v,0))); - case C_int64: - CAMLreturn_type(SWIG_Int64_val(SWIG_Field(v,0))); - case C_float: - case C_double: - CAMLreturn_type(Double_val(SWIG_Field(v,0))); - default: - fprintf( stderr, "Unknown block tag %d\n", SWIG_Tag_val(v) ); - failwith("No conversion to double"); - } - } - - SWIGSTATIC int caml_ptr_val_internal( CAML_VALUE v, void **out, - swig_type_info *descriptor ) { - CAMLparam1(v); - void *outptr = NULL; - swig_type_info *outdescr = NULL; - - if( v == Val_unit ) { - *out = 0; - CAMLreturn(0); - } - if( !Is_block(v) ) return -1; - switch( SWIG_Tag_val(v) ) { - case C_int: - if( !caml_long_val( v ) ) { - *out = 0; - CAMLreturn(0); - } else { - *out = 0; - CAMLreturn(1); - } - break; - case C_obj: - CAMLreturn - (caml_ptr_val_internal - (callback(*caml_named_value("caml_obj_ptr"),v), - out,descriptor)); - case C_string: - outptr = (void *)String_val(SWIG_Field(v,0)); - break; - case C_ptr: - outptr = (void *)(long)SWIG_Int64_val(SWIG_Field(v,0)); - outdescr = (swig_type_info *)(long)SWIG_Int64_val(SWIG_Field(v,1)); - break; - default: - *out = 0; - CAMLreturn(1); - break; - } - - CAMLreturn(SWIG_GetPtr(outptr,out,outdescr,descriptor)); - } - - SWIGSTATIC void *caml_ptr_val( CAML_VALUE v, swig_type_info *descriptor ) { - CAMLparam0(); -#ifdef TYPE_CAST_VERBOSE - caml_print_val( v ); -#endif - void *out = NULL; - if( !caml_ptr_val_internal( v, &out, descriptor ) ) - CAMLreturn_type(out); - else - failwith( "No appropriate conversion found." ); - } - - SWIGSTATIC char *caml_string_val( CAML_VALUE v ) { - return (char *)caml_ptr_val( v, 0 ); - } - - SWIGSTATIC int caml_string_len( CAML_VALUE v ) { - switch( SWIG_Tag_val(v) ) { - case C_string: - return string_length(SWIG_Field(v,0)); - default: - return strlen((char *)caml_ptr_val(v,0)); - } - } - - SWIGSTATIC int caml_bool_check( CAML_VALUE v ) { - CAMLparam1(v); - - if( !Is_block(v) ) return 0; - - switch( SWIG_Tag_val(v) ) { - case C_bool: - case C_ptr: - case C_string: - CAMLreturn(1); - default: - CAMLreturn(0); - } - } - - SWIGSTATIC int caml_int_check( CAML_VALUE v ) { - CAMLparam1(v); - - if( !Is_block(v) ) return 0; - - switch( SWIG_Tag_val(v) ) { - case C_char: - case C_uchar: - case C_short: - case C_ushort: - case C_int: - case C_uint: - case C_int32: - case C_int64: - CAMLreturn(1); - - default: - CAMLreturn(0); - } - } - - SWIGSTATIC int caml_float_check( CAML_VALUE v ) { - CAMLparam1(v); - if( !Is_block(v) ) return 0; - - switch( SWIG_Tag_val(v) ) { - case C_float: - case C_double: - CAMLreturn(1); - - default: - CAMLreturn(0); - } - } - - SWIGSTATIC int caml_ptr_check( CAML_VALUE v ) { - CAMLparam1(v); - if( !Is_block(v) ) return 0; - - switch( SWIG_Tag_val(v) ) { - case C_string: - case C_ptr: - case C_int64: - CAMLreturn(1); - - default: - CAMLreturn(0); - } - } - - static swig_module_info *SWIG_Ocaml_GetModule(void *SWIGUNUSEDPARM(clientdata)) { - CAML_VALUE pointer; - - pointer = callback(*caml_named_value("swig_find_type_info"), caml_val_int(0)); - if (Is_block(pointer) && SWIG_Tag_val(pointer) == C_ptr) { - return (swig_module_info *)(void *)(long)SWIG_Int64_val(SWIG_Field(pointer,0)); - } - return 0; - } - - static void SWIG_Ocaml_SetModule(swig_module_info *pointer) { - CAML_VALUE mod_pointer; - - mod_pointer = caml_val_ptr(pointer, NULL); - callback(*caml_named_value("swig_set_type_info"), mod_pointer); - } - -#ifdef __cplusplus } #endif -#undef value + +%typemap(in) SWIGTYPE { + $1 = *(($&1_ltype) caml_ptr_val($input,$&1_descriptor)) ; +} + +#ifdef __cplusplus + +%typemap(out) SWIGTYPE { + $&1_ltype temp = new $ltype((const $1_ltype &) $1); + $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)temp, $&1_descriptor); +} + +#else + +%typemap(out) SWIGTYPE { + void *temp = calloc(1,sizeof($ltype)); + memmove(temp, &$1, sizeof($1_type)); + $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", temp, $&1_descriptor); +} + +#endif + +%typemap(directorin) SWIGTYPE { + $<ype temp = new $ltype((const $ltype &)$1); + swig_result = SWIG_Ocaml_ptr_to_val("create_$ltype_from_ptr", (void *)temp, $&1_descriptor); + args = caml_list_append(args, swig_result); +} + +%typemap(directorin) SWIGTYPE *, SWIGTYPE [], SWIGTYPE &, SWIGTYPE && { + swig_result = SWIG_Ocaml_ptr_to_val("create_$ltype_from_ptr", (void *)&$1, $&1_descriptor); + args = caml_list_append(args, swig_result); +} + +/* The SIMPLE_MAP macro below defines the whole set of typemaps needed + for simple types. */ + +%define SIMPLE_MAP(C_NAME, C_TO_OCAML, OCAML_TO_C) +/* In */ +%typemap(in) C_NAME { + $1 = OCAML_TO_C($input); +} +%typemap(varin) C_NAME { + $1 = OCAML_TO_C($input); +} +%typemap(in) const C_NAME & ($*1_ltype temp) { + temp = ($*1_ltype) OCAML_TO_C($input); + $1 = &temp; +} +%typemap(varin) const C_NAME & { + $1 = OCAML_TO_C($input); +} +%typemap(directorout) C_NAME { + $1 = OCAML_TO_C($input); +} +/* Out */ +%typemap(out) C_NAME { + $result = C_TO_OCAML($1); +} +%typemap(varout) C_NAME { + $result = C_TO_OCAML($1); +} +%typemap(varout) const C_NAME & { + $result = C_TO_OCAML($1); +} +%typemap(out) const C_NAME & { + $result = C_TO_OCAML(*$1); +} +%typemap(directorin) C_NAME { + args = caml_list_append(args, C_TO_OCAML($1)); +} +%enddef + +SIMPLE_MAP(bool, caml_val_bool, caml_long_val); +SIMPLE_MAP(char, caml_val_char, caml_long_val); +SIMPLE_MAP(signed char, caml_val_char, caml_long_val); +SIMPLE_MAP(unsigned char, caml_val_uchar, caml_long_val); +SIMPLE_MAP(int, caml_val_int, caml_long_val); +SIMPLE_MAP(short, caml_val_short, caml_long_val); +SIMPLE_MAP(wchar_t, caml_val_short, caml_long_val); +SIMPLE_MAP(long, caml_val_long, caml_long_val); +SIMPLE_MAP(ptrdiff_t, caml_val_int, caml_long_val); +SIMPLE_MAP(unsigned int, caml_val_uint, caml_long_val); +SIMPLE_MAP(unsigned short, caml_val_ushort, caml_long_val); +SIMPLE_MAP(unsigned long, caml_val_ulong, caml_long_val); +SIMPLE_MAP(size_t, caml_val_int, caml_long_val); +SIMPLE_MAP(float, caml_val_float, caml_double_val); +SIMPLE_MAP(double, caml_val_double, caml_double_val); +SIMPLE_MAP(long long,caml_val_ulong,caml_long_val); +SIMPLE_MAP(unsigned long long,caml_val_ulong,caml_long_val); + +/* Void */ + +%typemap(out) void "$result = Val_unit;"; + +/* Pass through value */ + +%typemap (in) CAML_VALUE "$1=$input;"; +%typemap (out) CAML_VALUE "$result=$1;"; + +#if 0 +%include +#endif + +/* Handle char arrays as strings */ + +%define %char_ptr_in(how) +%typemap(how) char *, signed char *, unsigned char * { + $1 = ($ltype)caml_string_val($input); +} +/* Again work around the empty array bound bug */ +%typemap(how) char [ANY], signed char [ANY], unsigned char [ANY] { + char *temp = caml_string_val($input); + strcpy((char *)$1,temp); +} +%enddef + +%char_ptr_in(in); +%char_ptr_in(varin); +%char_ptr_in(directorout); + +%define %char_ptr_out(how) +%typemap(how) + char *, signed char *, unsigned char *, + const char *, const signed char *, const unsigned char * { + $result = caml_val_string((char *)$1); +} +/* I'd like to use the length here but can't because it might be empty */ +%typemap(how) + char [ANY], signed char [ANY], unsigned char [ANY], + const char [ANY], const signed char [ANY], const unsigned char [ANY] { + $result = caml_val_string((char *)$1); +} +%enddef + +%char_ptr_out(out); +%char_ptr_out(varout); +%char_ptr_out(directorin); + +%define %swigtype_ptr_in(how) +%typemap(how) SWIGTYPE * { + $1 = ($ltype)caml_ptr_val($input,$1_descriptor); +} +%typemap(how) SWIGTYPE (CLASS::*) { + void *v = caml_ptr_val($input,$1_descriptor); + memcpy(& $1, &v, sizeof(v)); +} +%enddef + +%typemap(out) SWIGTYPE * { + $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)$1, $1_descriptor); +} + +%define %swigtype_ptr_out(how) +%typemap(how) SWIGTYPE (CLASS::*) { + void *v; + memcpy(&v,& $1, sizeof(void *)); + $result = caml_val_ptr (v,$1_descriptor); +} +%enddef + +%swigtype_ptr_in(in); +%swigtype_ptr_in(varin); +%swigtype_ptr_in(directorout); +%swigtype_ptr_out(out); +%swigtype_ptr_out(varout); +%swigtype_ptr_out(directorin); + +%define %swigtype_array_fail(how,msg) +%typemap(how) SWIGTYPE [] { + caml_failwith(msg); +} +%enddef + +%swigtype_array_fail(in,"Array arguments for arbitrary types need a typemap"); +%swigtype_array_fail(varin,"Assignment to global arrays for arbitrary types need a typemap"); +%swigtype_array_fail(out,"Array arguments for arbitrary types need a typemap"); +%swigtype_array_fail(varout,"Array variables need a typemap"); +%swigtype_array_fail(directorin,"Array results with arbitrary types need a typemap"); +%swigtype_array_fail(directorout,"Array arguments with arbitrary types need a typemap"); + +/* C++ References */ + +/* Enums */ +%define %swig_enum_in(how) +%typemap(how) enum SWIGTYPE { + $1 = ($type)caml_long_val_full($input,"$type_marker"); +} +%enddef + +%define %swig_enum_out(how) +%typemap(how) enum SWIGTYPE { + $result = caml_callback2(*caml_named_value(SWIG_MODULE "_int_to_enum"),*caml_named_value("$type_marker"),Val_int((int)$1)); +} +%enddef + +%swig_enum_in(in) +%swig_enum_in(varin) +%swig_enum_in(directorout) +%swig_enum_out(out) +%swig_enum_out(varout) +%swig_enum_out(directorin) + +%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) { + $1 = ($1_ltype) caml_string_val($input); + $2 = ($2_ltype) caml_string_len($input); +} + +%typemap(out) SWIGTYPE *DYNAMIC, SWIGTYPE &DYNAMIC { + swig_type_info *ty = SWIG_TypeDynamicCast($1_descriptor, (void **)&$1); + $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)$1, ty); +} + +/* Array reference typemaps */ +%apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } +%apply SWIGTYPE && { SWIGTYPE ((&)[ANY]) } + +/* const pointers */ +%apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } diff --git a/Lib/ocaml/ocamlkw.swg b/Lib/ocaml/ocamlkw.swg index 92d822219..5e66085e0 100644 --- a/Lib/ocaml/ocamlkw.swg +++ b/Lib/ocaml/ocamlkw.swg @@ -6,12 +6,13 @@ /* from - http://caml.inria.fr/ocaml/htmlman/manual044.html + https://caml.inria.fr/pub/docs/manual-ocaml/lex.html */ OCAMLKW(and); OCAMLKW(as); +OCAMLKW(asr); OCAMLKW(assert); OCAMLKW(begin); OCAMLKW(class); @@ -33,13 +34,20 @@ OCAMLKW(in); OCAMLKW(include); OCAMLKW(inherit); OCAMLKW(initializer); +OCAMLKW(land); OCAMLKW(lazy); OCAMLKW(let); +OCAMLKW(lor); +OCAMLKW(lsl); +OCAMLKW(lsr); +OCAMLKW(lxor); OCAMLKW(match); OCAMLKW(method); +OCAMLKW(mod); OCAMLKW(module); OCAMLKW(mutable); OCAMLKW(new); +OCAMLKW(nonrec); OCAMLKW(object); OCAMLKW(of); OCAMLKW(open); diff --git a/Lib/ocaml/ocamlrun.swg b/Lib/ocaml/ocamlrun.swg new file mode 100644 index 000000000..3d552cc50 --- /dev/null +++ b/Lib/ocaml/ocamlrun.swg @@ -0,0 +1,607 @@ +/* -*-c-*- */ + +/* SWIG pointer structure */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define C_bool 0 +#define C_char 1 +#define C_uchar 2 +#define C_short 3 +#define C_ushort 4 +#define C_int 5 +#define C_uint 6 +#define C_int32 7 +#define C_int64 8 +#define C_float 9 +#define C_double 10 +#define C_ptr 11 +#define C_array 12 +#define C_list 13 +#define C_obj 14 +#define C_string 15 +#define C_enum 16 +#define C_director_core 17 + + +/* Cast a pointer if possible; returns 1 if successful */ + + SWIGINTERN int + SWIG_Cast (void *source, swig_type_info *source_type, + void **ptr, swig_type_info *dest_type) + { + if( !source ) { /* Special case for NULL. This is a popular question + for other modules on the list, so I want an easy way out... */ + *ptr = 0; + return 0; + } + +#ifdef TYPE_CAST_VERBOSE + fprintf( stderr, "Trying to cast %s to %s\n", + source_type ? source_type->str : "", + dest_type ? dest_type->str : "" ); +#endif + if (dest_type != source_type) { + /* We have a type mismatch. Will have to look through our type + mapping table to figure out whether or not we can accept this + datatype. + -- + Ignore typechecks for void *. Allow any conversion. */ + if( !dest_type || !source_type || + !strcmp(dest_type->name,"_p_void") || + !strcmp(source_type->name,"_p_void") ) { + *ptr = source; + return 0; + } else { + swig_cast_info *tc = + SWIG_TypeCheckStruct(source_type, dest_type ); +#ifdef TYPE_CAST_VERBOSE + fprintf( stderr, "Typecheck -> %s\n", + tc ? tc->type->str : "" ); +#endif + if( tc ) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc, source, &newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + return 0; + } else + return -1; + } + } else { + *ptr = source; + return 0; + } + } + +/* Return 0 if successful. */ + SWIGINTERN int + SWIG_GetPtr(void *inptr, void **outptr, + swig_type_info *intype, swig_type_info *outtype) { + if (intype) { + return SWIG_Cast(inptr, intype, + outptr, outtype) == -1; + } else { + *outptr = inptr; + return 0; + } + } + + SWIGINTERN void caml_print_list( CAML_VALUE v ); + + SWIGINTERN void caml_print_val( CAML_VALUE v ) { + switch( SWIG_Tag_val(v) ) { + case C_bool: + if( Bool_val(SWIG_Field(v,0)) ) fprintf( stderr, "true " ); + else fprintf( stderr, "false " ); + break; + case C_char: + case C_uchar: + fprintf( stderr, "'%c' (\\%03d) ", + (Int_val(SWIG_Field(v,0)) >= ' ' && + Int_val(SWIG_Field(v,0)) < 127) ? Int_val(SWIG_Field(v,0)) : '.', + Int_val(SWIG_Field(v,0)) ); + break; + case C_short: + case C_ushort: + case C_int: + fprintf( stderr, "%d ", (int)caml_long_val(v) ); + break; + + case C_uint: + case C_int32: + fprintf( stderr, "%ud ", (unsigned int)caml_long_val(v) ); + break; + case C_int64: + fprintf( stderr, "%ld ", caml_long_val(v) ); + break; + case C_float: + case C_double: + fprintf( stderr, "%f ", caml_double_val(v) ); + break; + + case C_ptr: + { + void *vout = 0; + swig_type_info *ty = (swig_type_info *)(long)SWIG_Int64_val(SWIG_Field(v,1)); + caml_ptr_val_internal(v,&vout,0); + fprintf( stderr, "PTR(%p,%s) ", + vout, + ty ? ty->name : "(null)" ); + } + break; + case C_array: + { + unsigned int i; + for( i = 0; i < Wosize_val( SWIG_Field(v,0) ); i++ ) + caml_print_val( SWIG_Field(SWIG_Field(v,0),i) ); + } + break; + case C_list: + caml_print_list( SWIG_Field(v,0) ); + break; + case C_obj: + fprintf( stderr, "OBJ(%p) ", (void *)SWIG_Field(v,0) ); + break; + case C_string: + { + void *cout; + caml_ptr_val_internal(v,&cout,0); + fprintf( stderr, "'%s' ", (char *)cout ); + } + break; + } + } + + SWIGINTERN void caml_print_list( CAML_VALUE v ) { + CAMLparam1(v); + while( v && Is_block(v) ) { + fprintf( stderr, "[ " ); + caml_print_val( SWIG_Field(v,0) ); + fprintf( stderr, "]\n" ); + v = SWIG_Field(v,1); + } + CAMLreturn0; + } + + SWIGINTERN CAML_VALUE caml_list_nth( CAML_VALUE lst, int n ) { + CAMLparam1(lst); + int i = 0; + while( i < n && lst && Is_block(lst) ) { + i++; lst = SWIG_Field(lst,1); + } + if( lst == Val_unit ) CAMLreturn(Val_unit); + else CAMLreturn(SWIG_Field(lst,0)); + } + + SWIGINTERN CAML_VALUE caml_list_append( CAML_VALUE lst, CAML_VALUE elt ) { + CAMLparam2(lst,elt); + SWIG_CAMLlocal3(v,vt,lh); + lh = Val_unit; + v = Val_unit; + + /* Appending C_void should have no effect */ + if( !Is_block(elt) ) return lst; + + while( lst && Is_block(lst) ) { + if( v && v != Val_unit ) { + vt = caml_alloc_tuple(2); + SWIG_Store_field(v,1,vt); + v = vt; + } else { + v = lh = caml_alloc_tuple(2); + } + SWIG_Store_field(v,0,SWIG_Field(lst,0)); + lst = SWIG_Field(lst,1); + } + + if( v && Is_block(v) ) { + vt = caml_alloc_tuple(2); + SWIG_Store_field(v,1,vt); + v = vt; + } else { + v = lh = caml_alloc_tuple(2); + } + SWIG_Store_field(v,0,elt); + SWIG_Store_field(v,1,Val_unit); + + CAMLreturn(lh); + } + + SWIGINTERN int caml_list_length( CAML_VALUE lst ) { + CAMLparam1(lst); + int i = 0; + while( lst && Is_block(lst) ) { i++; lst = SWIG_Field(lst,1); } + CAMLreturn(i); + } + + SWIGINTERN void caml_array_set( CAML_VALUE arr, int n, CAML_VALUE item ) { + CAMLparam2(arr,item); + SWIG_Store_field(SWIG_Field(arr,0),n,item); + CAMLreturn0; + } + + SWIGINTERN value caml_array_nth( CAML_VALUE arr, int n ) { + CAMLparam1(arr); + if( SWIG_Tag_val(arr) == C_array ) + CAMLreturn(SWIG_Field(SWIG_Field(arr,0),n)); + else if( SWIG_Tag_val(arr) == C_list ) + CAMLreturn(caml_list_nth(arr,0)); + else + caml_failwith("Need array or list"); + } + + SWIGINTERN int caml_array_len( CAML_VALUE arr ) { + CAMLparam1(arr); + if( SWIG_Tag_val(arr) == C_array ) + CAMLreturn(Wosize_val(SWIG_Field(arr,0))); + else if( SWIG_Tag_val(arr) == C_list ) + CAMLreturn(caml_list_length(arr)); + else + caml_failwith("Need array or list"); + } + + SWIGINTERN CAML_VALUE caml_swig_alloc(int x,int y) { + return caml_alloc(x,y); + } + + SWIGINTERN value caml_array_new( int n ) { + CAMLparam0(); + SWIG_CAMLlocal1(vv); + vv = caml_swig_alloc(1,C_array); + SWIG_Store_field(vv,0,caml_alloc_tuple(n)); + CAMLreturn(vv); + } + + SWIGINTERN CAML_VALUE caml_val_bool( int b ) { + CAMLparam0(); + SWIG_CAMLlocal1(bv); + bv = caml_swig_alloc(1,C_bool); + SWIG_Store_field(bv,0,Val_bool(b)); + CAMLreturn(bv); + } + + SWIGINTERN CAML_VALUE caml_val_char( char c ) { + CAMLparam0(); + SWIG_CAMLlocal1(cv); + cv = caml_swig_alloc(1,C_char); + SWIG_Store_field(cv,0,Val_int(c)); + CAMLreturn(cv); + } + + SWIGINTERN CAML_VALUE caml_val_uchar( unsigned char uc ) { + CAMLparam0(); + SWIG_CAMLlocal1(ucv); + ucv = caml_swig_alloc(1,C_uchar); + SWIG_Store_field(ucv,0,Val_int(uc)); + CAMLreturn(ucv); + } + + SWIGINTERN CAML_VALUE caml_val_short( short s ) { + CAMLparam0(); + SWIG_CAMLlocal1(sv); + sv = caml_swig_alloc(1,C_short); + SWIG_Store_field(sv,0,Val_int(s)); + CAMLreturn(sv); + } + + SWIGINTERN CAML_VALUE caml_val_ushort( unsigned short us ) { + CAMLparam0(); + SWIG_CAMLlocal1(usv); + usv = caml_swig_alloc(1,C_ushort); + SWIG_Store_field(usv,0,Val_int(us)); + CAMLreturn(usv); + } + + SWIGINTERN CAML_VALUE caml_val_int( int i ) { + CAMLparam0(); + SWIG_CAMLlocal1(iv); + iv = caml_swig_alloc(1,C_int); + SWIG_Store_field(iv,0,Val_int(i)); + CAMLreturn(iv); + } + + SWIGINTERN CAML_VALUE caml_val_uint( unsigned int ui ) { + CAMLparam0(); + SWIG_CAMLlocal1(uiv); + uiv = caml_swig_alloc(1,C_int); + SWIG_Store_field(uiv,0,Val_int(ui)); + CAMLreturn(uiv); + } + + SWIGINTERN CAML_VALUE caml_val_long( long l ) { + CAMLparam0(); + SWIG_CAMLlocal1(lv); + lv = caml_swig_alloc(1,C_int64); + SWIG_Store_field(lv,0,caml_copy_int64(l)); + CAMLreturn(lv); + } + + SWIGINTERN CAML_VALUE caml_val_ulong( unsigned long ul ) { + CAMLparam0(); + SWIG_CAMLlocal1(ulv); + ulv = caml_swig_alloc(1,C_int64); + SWIG_Store_field(ulv,0,caml_copy_int64(ul)); + CAMLreturn(ulv); + } + + SWIGINTERN CAML_VALUE caml_val_float( float f ) { + CAMLparam0(); + SWIG_CAMLlocal1(fv); + fv = caml_swig_alloc(1,C_float); + SWIG_Store_field(fv,0,caml_copy_double((double)f)); + CAMLreturn(fv); + } + + SWIGINTERN CAML_VALUE caml_val_double( double d ) { + CAMLparam0(); + SWIG_CAMLlocal1(fv); + fv = caml_swig_alloc(1,C_double); + SWIG_Store_field(fv,0,caml_copy_double(d)); + CAMLreturn(fv); + } + + SWIGINTERN CAML_VALUE caml_val_ptr( void *p, swig_type_info *info ) { + CAMLparam0(); + SWIG_CAMLlocal1(vv); + vv = caml_swig_alloc(2,C_ptr); + SWIG_Store_field(vv,0,caml_copy_int64((long)p)); + SWIG_Store_field(vv,1,caml_copy_int64((long)info)); + CAMLreturn(vv); + } + + SWIGINTERN CAML_VALUE caml_val_string( const char *p ) { + CAMLparam0(); + SWIG_CAMLlocal1(vv); + if( !p ) CAMLreturn(caml_val_ptr( (void *)p, 0 )); + vv = caml_swig_alloc(1,C_string); + SWIG_Store_field(vv,0,caml_copy_string(p)); + CAMLreturn(vv); + } + + SWIGINTERN CAML_VALUE caml_val_string_len( const char *p, int len ) { + CAMLparam0(); + SWIG_CAMLlocal1(vv); + if( !p || len < 0 ) CAMLreturn(caml_val_ptr( (void *)p, 0 )); + vv = caml_swig_alloc(1,C_string); + SWIG_Store_field(vv,0,caml_alloc_string(len)); + memcpy(String_val(SWIG_Field(vv,0)),p,len); + CAMLreturn(vv); + } + + #define caml_val_obj(v, name) caml_val_obj_helper(v, SWIG_TypeQuery((name)), name) + SWIGINTERN CAML_VALUE caml_val_obj_helper( void *v, swig_type_info *type, char *name) { + CAMLparam0(); + CAMLreturn(caml_callback2(*caml_named_value("caml_create_object_fn"), + caml_val_ptr(v,type), + caml_copy_string(name))); + } + + SWIGINTERN long caml_long_val_full( CAML_VALUE v, const char *name ) { + CAMLparam1(v); + if( !Is_block(v) ) return 0; + + switch( SWIG_Tag_val(v) ) { + case C_bool: + case C_char: + case C_uchar: + case C_short: + case C_ushort: + case C_int: + CAMLreturn(Int_val(SWIG_Field(v,0))); + case C_uint: + case C_int32: + CAMLreturn(Int32_val(SWIG_Field(v,0))); + case C_int64: + CAMLreturn((long)SWIG_Int64_val(SWIG_Field(v,0))); + case C_float: + case C_double: + CAMLreturn((long)Double_val(SWIG_Field(v,0))); + case C_string: + CAMLreturn((long)String_val(SWIG_Field(v,0))); + case C_ptr: + CAMLreturn((long)SWIG_Int64_val(SWIG_Field(SWIG_Field(v,0),0))); + case C_enum: { + SWIG_CAMLlocal1(ret); + CAML_VALUE *enum_to_int = caml_named_value(SWIG_MODULE "_enum_to_int"); + if( !name ) caml_failwith( "Not an enum conversion" ); + ret = caml_callback2(*enum_to_int,*caml_named_value(name),v); + CAMLreturn(caml_long_val(ret)); + } + default: + caml_failwith("No conversion to int"); + } + } + + SWIGINTERN long caml_long_val( CAML_VALUE v ) { + return caml_long_val_full(v,0); + } + + SWIGINTERN double caml_double_val( CAML_VALUE v ) { + CAMLparam1(v); + if( !Is_block(v) ) return 0.0; + switch( SWIG_Tag_val(v) ) { + case C_bool: + case C_char: + case C_uchar: + case C_short: + case C_ushort: + case C_int: + CAMLreturn_type(Int_val(SWIG_Field(v,0))); + case C_uint: + case C_int32: + CAMLreturn_type(Int32_val(SWIG_Field(v,0))); + case C_int64: + CAMLreturn_type(SWIG_Int64_val(SWIG_Field(v,0))); + case C_float: + case C_double: + CAMLreturn_type(Double_val(SWIG_Field(v,0))); + default: + fprintf( stderr, "Unknown block tag %d\n", SWIG_Tag_val(v) ); + caml_failwith("No conversion to double"); + } + } + + SWIGINTERN int caml_ptr_val_internal( CAML_VALUE v, void **out, + swig_type_info *descriptor ) { + CAMLparam1(v); + void *outptr = NULL; + swig_type_info *outdescr = NULL; + static CAML_VALUE *func_val = NULL; + + if( v == Val_unit ) { + *out = 0; + CAMLreturn_type(0); + } + if( !Is_block(v) ) return -1; + switch( SWIG_Tag_val(v) ) { + case C_obj: + if (!func_val) { + func_val = caml_named_value("caml_obj_ptr"); + } + CAMLreturn_type(caml_ptr_val_internal(caml_callback(*func_val, v), out, descriptor)); + case C_string: + outptr = (void *)String_val(SWIG_Field(v,0)); + break; + case C_ptr: + outptr = (void *)(long)SWIG_Int64_val(SWIG_Field(v,0)); + outdescr = (swig_type_info *)(long)SWIG_Int64_val(SWIG_Field(v,1)); + break; + default: + *out = 0; + CAMLreturn_type(1); + break; + } + + CAMLreturn_type(SWIG_GetPtr(outptr, out, outdescr, descriptor)); + } + + SWIGINTERN void *caml_ptr_val( CAML_VALUE v, swig_type_info *descriptor ) { + CAMLparam0(); +#ifdef TYPE_CAST_VERBOSE + caml_print_val( v ); +#endif + void *out = NULL; + if( !caml_ptr_val_internal( v, &out, descriptor ) ) + CAMLreturn_type(out); + else + caml_failwith( "No appropriate conversion found." ); + } + + SWIGINTERN char *caml_string_val( CAML_VALUE v ) { + return (char *)caml_ptr_val( v, 0 ); + } + + SWIGINTERN int caml_string_len( CAML_VALUE v ) { + switch( SWIG_Tag_val(v) ) { + case C_string: + return caml_string_length(SWIG_Field(v,0)); + default: + return strlen((char *)caml_ptr_val(v,0)); + } + } + + SWIGINTERN int caml_bool_check( CAML_VALUE v ) { + CAMLparam1(v); + + if( !Is_block(v) ) return 0; + + switch( SWIG_Tag_val(v) ) { + case C_bool: + case C_ptr: + case C_string: + CAMLreturn(1); + default: + CAMLreturn(0); + } + } + + SWIGINTERN int caml_int_check( CAML_VALUE v ) { + CAMLparam1(v); + + if( !Is_block(v) ) return 0; + + switch( SWIG_Tag_val(v) ) { + case C_char: + case C_uchar: + case C_short: + case C_ushort: + case C_int: + case C_uint: + case C_int32: + case C_int64: + CAMLreturn(1); + + default: + CAMLreturn(0); + } + } + + SWIGINTERN int caml_float_check( CAML_VALUE v ) { + CAMLparam1(v); + if( !Is_block(v) ) return 0; + + switch( SWIG_Tag_val(v) ) { + case C_float: + case C_double: + CAMLreturn(1); + + default: + CAMLreturn(0); + } + } + + SWIGINTERN int caml_ptr_check( CAML_VALUE v ) { + CAMLparam1(v); + if( !Is_block(v) ) return 0; + + switch( SWIG_Tag_val(v) ) { + case C_string: + case C_ptr: + case C_int64: + CAMLreturn(1); + + default: + CAMLreturn(0); + } + } + + SWIGINTERN CAML_VALUE SWIG_Ocaml_ptr_to_val(const char *name, void *ptr, swig_type_info *descriptor) { + CAMLparam0(); + SWIG_CAMLlocal1(result); + + CAML_VALUE *fromval = caml_named_value(name); + if (fromval) { + result = caml_callback(*fromval, caml_val_ptr(ptr, descriptor)); + } else { + result = caml_val_ptr(ptr, descriptor); + } + CAMLreturn(result); + } + + static swig_module_info *SWIG_Ocaml_GetModule(void *SWIGUNUSEDPARM(clientdata)) { + CAML_VALUE pointer; + + pointer = caml_callback(*caml_named_value("swig_find_type_info"), caml_val_int(0)); + if (Is_block(pointer) && SWIG_Tag_val(pointer) == C_ptr) { + return (swig_module_info *)(void *)(long)SWIG_Int64_val(SWIG_Field(pointer,0)); + } + return 0; + } + + static void SWIG_Ocaml_SetModule(swig_module_info *pointer) { + CAML_VALUE mod_pointer; + + mod_pointer = caml_val_ptr(pointer, NULL); + caml_callback(*caml_named_value("swig_set_type_info"), mod_pointer); + } + +#ifdef __cplusplus +} +#endif +#undef value + diff --git a/Lib/ocaml/ocamldec.swg b/Lib/ocaml/ocamlrundec.swg similarity index 51% rename from Lib/ocaml/ocamldec.swg rename to Lib/ocaml/ocamlrundec.swg index 96e1cd2ce..555f9a44f 100644 --- a/Lib/ocaml/ocamldec.swg +++ b/Lib/ocaml/ocamlrundec.swg @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * ocamldec.swg + * ocamlrundec.swg * * Ocaml runtime code -- declarations * ----------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ SWIGEXT { #endif #define value caml_value_t #define CAML_VALUE caml_value_t +#define CAML_NAME_SPACE #include #include #include @@ -24,9 +25,16 @@ SWIGEXT { #include #include +#if defined(CAMLassert) +/* Both this macro and version.h were introduced in version 4.02.0 */ +#include +#else +#define OCAML_VERSION 0 /* Unknown, but < 40200 */ +#endif + #define caml_array_set swig_caml_array_set -// Adapted from memory.h and mlvalues.h +/* Adapted from memory.h and mlvalues.h */ #define SWIG_CAMLlocal1(x) \ caml_value_t x = 0; \ @@ -56,7 +64,7 @@ SWIGEXT { #define SWIG_Store_field(block, offset, val) do{ \ mlsize_t caml__temp_offset = (offset); \ caml_value_t caml__temp_val = (val); \ - modify (&SWIG_Field ((block), caml__temp_offset), caml__temp_val); \ + caml_modify (&SWIG_Field ((block), caml__temp_offset), caml__temp_val); \ }while(0) #define SWIG_Data_custom_val(v) ((void *) &SWIG_Field((v), 1)) @@ -101,9 +109,17 @@ SWIGEXT { #ifndef ARCH_ALIGN_INT64 +#if OCAML_VERSION >= 40300 +#define SWIG_Int64_val(v) (*((int64_t *) SWIG_Data_custom_val(v))) +#else #define SWIG_Int64_val(v) (*((int64 *) SWIG_Data_custom_val(v))) +#endif +#else +#if OCAML_VERSION >= 40300 +CAMLextern int64_t Int64_val(caml_value_t v); #else CAMLextern int64 Int64_val(caml_value_t v); +#endif #define SWIG_Int64_val(v) Int64_val(v) #endif @@ -111,56 +127,85 @@ CAMLextern int64 Int64_val(caml_value_t v); #define SWIG_GetModule(clientdata) SWIG_Ocaml_GetModule(clientdata) #define SWIG_SetModule(clientdata, pointer) SWIG_Ocaml_SetModule(pointer) -#define SWIG_contract_assert(expr, msg) if(!(expr)) {failwith(msg);} else +typedef enum { + SWIG_OCamlArithmeticException, + SWIG_OCamlDirectorPureVirtual, + SWIG_OCamlOutOfMemoryError, + SWIG_OCamlOverflowException, + SWIG_OCamlIllegalArgumentException, + SWIG_OCamlIndexOutOfBoundsException, + SWIG_OCamlRuntimeException, + SWIG_OCamlSystemException, + SWIG_OCamlUnknownError +} SWIG_OCamlExceptionCodes; - SWIGSTATIC int +SWIGINTERN void SWIG_OCamlThrowException(SWIG_OCamlExceptionCodes code, const char *msg) { + CAMLparam0(); + SWIG_CAMLlocal1(str); + + switch (code) { + case SWIG_OCamlIllegalArgumentException: + caml_invalid_argument(msg); + break; + case SWIG_OCamlSystemException: + str = caml_copy_string(msg); + caml_raise_sys_error(str); + break; + case SWIG_OCamlArithmeticException: + case SWIG_OCamlIndexOutOfBoundsException: + case SWIG_OCamlOutOfMemoryError: + case SWIG_OCamlOverflowException: + case SWIG_OCamlRuntimeException: + case SWIG_OCamlUnknownError: + default: + caml_failwith(msg); + break; + } + CAMLreturn0; +} + +#define SWIG_contract_assert(expr, msg) if(!(expr)) {SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, msg);} + + SWIGINTERN int SWIG_GetPtr(void *source, void **result, swig_type_info *type, swig_type_info *result_type); + + SWIGINTERN CAML_VALUE caml_list_nth( CAML_VALUE lst, int n ); + SWIGINTERN CAML_VALUE caml_list_append( CAML_VALUE lst, CAML_VALUE elt ); + SWIGINTERN int caml_list_length( CAML_VALUE lst ); + SWIGINTERN CAML_VALUE caml_array_new( int n ); + SWIGINTERN void caml_array_set( CAML_VALUE arr, int n, CAML_VALUE item ); + SWIGINTERN CAML_VALUE caml_array_nth( CAML_VALUE arr, int n ); + SWIGINTERN int caml_array_len( CAML_VALUE arr ); + + SWIGINTERN CAML_VALUE caml_val_char( char c ); + SWIGINTERN CAML_VALUE caml_val_uchar( unsigned char c ); + + SWIGINTERN CAML_VALUE caml_val_short( short s ); + SWIGINTERN CAML_VALUE caml_val_ushort( unsigned short s ); - SWIGSTATIC void * - SWIG_MustGetPtr (CAML_VALUE v, swig_type_info *type); - - SWIGSTATIC CAML_VALUE _wrap_delete_void( CAML_VALUE ); - - SWIGSTATIC int enum_to_int( char *name, CAML_VALUE v ); - SWIGSTATIC CAML_VALUE int_to_enum( char *name, int v ); + SWIGINTERN CAML_VALUE caml_val_int( int x ); + SWIGINTERN CAML_VALUE caml_val_uint( unsigned int x ); - SWIGSTATIC CAML_VALUE caml_list_nth( CAML_VALUE lst, int n ); - SWIGSTATIC CAML_VALUE caml_list_append( CAML_VALUE lst, CAML_VALUE elt ); - SWIGSTATIC int caml_list_length( CAML_VALUE lst ); - SWIGSTATIC CAML_VALUE caml_array_new( int n ); - SWIGSTATIC void caml_array_set( CAML_VALUE arr, int n, CAML_VALUE item ); - SWIGSTATIC CAML_VALUE caml_array_nth( CAML_VALUE arr, int n ); - SWIGSTATIC int caml_array_len( CAML_VALUE arr ); + SWIGINTERN CAML_VALUE caml_val_long( long x ); + SWIGINTERN CAML_VALUE caml_val_ulong( unsigned long x ); - SWIGSTATIC CAML_VALUE caml_val_char( char c ); - SWIGSTATIC CAML_VALUE caml_val_uchar( unsigned char c ); + SWIGINTERN CAML_VALUE caml_val_float( float f ); + SWIGINTERN CAML_VALUE caml_val_double( double d ); - SWIGSTATIC CAML_VALUE caml_val_short( short s ); - SWIGSTATIC CAML_VALUE caml_val_ushort( unsigned short s ); - - SWIGSTATIC CAML_VALUE caml_val_int( int x ); - SWIGSTATIC CAML_VALUE caml_val_uint( unsigned int x ); + SWIGINTERN CAML_VALUE caml_val_ptr( void *p, swig_type_info *descriptor ); - SWIGSTATIC CAML_VALUE caml_val_long( long x ); - SWIGSTATIC CAML_VALUE caml_val_ulong( unsigned long x ); + SWIGINTERN CAML_VALUE caml_val_string( const char *str ); + SWIGINTERN CAML_VALUE caml_val_string_len( const char *str, int len ); - SWIGSTATIC CAML_VALUE caml_val_float( float f ); - SWIGSTATIC CAML_VALUE caml_val_double( double d ); + SWIGINTERN long caml_long_val( CAML_VALUE v ); + SWIGINTERN double caml_double_val( CAML_VALUE v ); - SWIGSTATIC CAML_VALUE caml_val_ptr( void *p, swig_type_info *descriptor ); - - SWIGSTATIC CAML_VALUE caml_val_string( const char *str ); - SWIGSTATIC CAML_VALUE caml_val_string_len( const char *str, int len ); - - SWIGSTATIC long caml_long_val( CAML_VALUE v ); - SWIGSTATIC double caml_double_val( CAML_VALUE v ); - - SWIGSTATIC int caml_ptr_val_internal( CAML_VALUE v, void **out, + SWIGINTERN int caml_ptr_val_internal( CAML_VALUE v, void **out, swig_type_info *descriptor ); - SWIGSTATIC void *caml_ptr_val( CAML_VALUE v, swig_type_info *descriptor ); + SWIGINTERN void *caml_ptr_val( CAML_VALUE v, swig_type_info *descriptor ); - SWIGSTATIC char *caml_string_val( CAML_VALUE v ); - SWIGSTATIC int caml_string_len( CAML_VALUE v ); + SWIGINTERN char *caml_string_val( CAML_VALUE v ); + SWIGINTERN int caml_string_len( CAML_VALUE v ); #ifdef __cplusplus } diff --git a/Lib/ocaml/std_common.i b/Lib/ocaml/std_common.i index 1c397050c..7e64607d9 100644 --- a/Lib/ocaml/std_common.i +++ b/Lib/ocaml/std_common.i @@ -7,13 +7,17 @@ %include %apply size_t { std::size_t }; +%apply const size_t& { const std::size_t& }; %{ #include - CAML_VALUE SwigString_FromString(const std::string& s) { - return caml_val_string((char *)s.c_str()); - } - std::string SwigString_AsString(CAML_VALUE o) { - return std::string((char *)caml_ptr_val(o,0)); - } +SWIGINTERNINLINE +CAML_VALUE SwigString_FromString(const std::string &s) { + return caml_val_string((char *)s.c_str()); +} + +SWIGINTERNINLINE +std::string SwigString_AsString(CAML_VALUE o) { + return std::string((char *)caml_ptr_val(o,0)); +} %} diff --git a/Lib/ocaml/std_except.i b/Lib/ocaml/std_except.i new file mode 100644 index 000000000..74ddcb51d --- /dev/null +++ b/Lib/ocaml/std_except.i @@ -0,0 +1,23 @@ +%{ +#include +#include +%} + +namespace std +{ + %ignore exception; + struct exception {}; +} + +%typemap(throws) std::bad_cast "SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, $1.what());" +%typemap(throws) std::bad_exception "SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, $1.what());" +%typemap(throws) std::domain_error "SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, $1.what());" +%typemap(throws) std::exception "SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, $1.what());" +%typemap(throws) std::invalid_argument "SWIG_OCamlThrowException(SWIG_OCamlIllegalArgumentException, $1.what());" +%typemap(throws) std::length_error "SWIG_OCamlThrowException(SWIG_OCamlIndexOutOfBoundsException, $1.what());" +%typemap(throws) std::logic_error "SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, $1.what());" +%typemap(throws) std::out_of_range "SWIG_OCamlThrowException(SWIG_OCamlIndexOutOfBoundsException, $1.what());" +%typemap(throws) std::overflow_error "SWIG_OCamlThrowException(SWIG_OCamlArithmeticException, $1.what());" +%typemap(throws) std::range_error "SWIG_OCamlThrowException(SWIG_OCamlIndexOutOfBoundsException, $1.what());" +%typemap(throws) std::runtime_error "SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, $1.what());" +%typemap(throws) std::underflow_error "SWIG_OCamlThrowException(SWIG_OCamlArithmeticException, $1.what());" diff --git a/Lib/ocaml/std_list.i b/Lib/ocaml/std_list.i index 06181cca8..e0524aa40 100644 --- a/Lib/ocaml/std_list.i +++ b/Lib/ocaml/std_list.i @@ -13,21 +13,24 @@ %} -namespace std{ +namespace std { template class list { public: - - typedef T &reference; - typedef const T& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; typedef T &iterator; typedef const T& const_iterator; - + list(); list(unsigned int size, const T& value = T()); - list(const list &); + list(const list& other); - ~list(); void assign(unsigned int n, const T& value); void swap(list &x); @@ -35,28 +38,25 @@ namespace std{ const_reference back(); const_iterator begin(); const_iterator end(); - + void resize(unsigned int n, T c = T()); bool empty() const; void push_front(const T& x); void push_back(const T& x); - void pop_front(); void pop_back(); void clear(); unsigned int size() const; unsigned int max_size() const; void resize(unsigned int n, const T& value); - + void remove(const T& value); void unique(); void reverse(); void sort(); - - - + %extend { const_reference __getitem__(int i) throw (std::out_of_range) @@ -206,9 +206,7 @@ namespace std{ { self->pop_back(); } - - }; - + } }; } diff --git a/Lib/ocaml/std_map.i b/Lib/ocaml/std_map.i index 5656b7fa2..3f197baa6 100644 --- a/Lib/ocaml/std_map.i +++ b/Lib/ocaml/std_map.i @@ -19,22 +19,28 @@ // exported class namespace std { - template class map { + template > class map { // add typemaps here public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -44,14 +50,14 @@ namespace std { (*self)[key] = x; } void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } } diff --git a/Lib/ocaml/std_pair.i b/Lib/ocaml/std_pair.i index fe45ee676..732347db5 100644 --- a/Lib/ocaml/std_pair.i +++ b/Lib/ocaml/std_pair.i @@ -18,12 +18,14 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/ocaml/std_string.i b/Lib/ocaml/std_string.i index bd5be0da2..712c3bb73 100644 --- a/Lib/ocaml/std_string.i +++ b/Lib/ocaml/std_string.i @@ -29,7 +29,6 @@ class wstring; /* Overloading check */ %typemap(in) string { - /* %typemap(in) string */ if (caml_ptr_check($input)) $1.assign((char *)caml_ptr_val($input,0), caml_string_len($input)); else @@ -37,7 +36,6 @@ class wstring; } %typemap(in) const string & ($*1_ltype temp) { - /* %typemap(in) const string & */ if (caml_ptr_check($input)) { temp.assign((char *)caml_ptr_val($input,0), caml_string_len($input)); $1 = &temp; @@ -47,7 +45,6 @@ class wstring; } %typemap(in) string & ($*1_ltype temp) { - /* %typemap(in) string & */ if (caml_ptr_check($input)) { temp.assign((char *)caml_ptr_val($input,0), caml_string_len($input)); $1 = &temp; @@ -57,7 +54,6 @@ class wstring; } %typemap(in) string * ($*1_ltype *temp) { - /* %typemap(in) string * */ if (caml_ptr_check($input)) { temp = new $*1_ltype((char *)caml_ptr_val($input,0), caml_string_len($input)); $1 = temp; @@ -71,24 +67,26 @@ class wstring; } %typemap(argout) string & { - /* %typemap(argout) string & */ swig_result = caml_list_append(swig_result,caml_val_string_len((*$1).c_str(), (*$1).size())); } +%typemap(directorin) string { + swig_result = caml_val_string_len($1.c_str(), $1.size()); + args = caml_list_append(args, swig_result); +} + %typemap(directorout) string { - /* %typemap(directorout) string */ $result.assign((char *)caml_ptr_val($input,0), caml_string_len($input)); } %typemap(out) string { - /* %typemap(out) string */ $result = caml_val_string_len($1.c_str(),$1.size()); } %typemap(out) string * { - /* %typemap(out) string * */ $result = caml_val_string_len((*$1).c_str(),(*$1).size()); } +%typemap(typecheck) string, const string & = char *; } #ifdef ENABLE_CHARPTR_ARRAY @@ -114,7 +112,7 @@ char **c_charptr_array( const std::vector &str_v ); let string_array_to_vector sa = let nv = _new_StringVector C_void in - array_to_vector nv (fun x -> C_string x) sa ; nv + ignore (array_to_vector nv (fun x -> C_string x) sa) ; nv let c_string_array ar = _c_charptr_array (string_array_to_vector ar) diff --git a/Lib/ocaml/std_vector.i b/Lib/ocaml/std_vector.i index 53d107447..891d038c9 100644 --- a/Lib/ocaml/std_vector.i +++ b/Lib/ocaml/std_vector.i @@ -41,9 +41,18 @@ namespace std { template class vector { public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + vector(unsigned int size = 0); vector(unsigned int size, const T& value); - vector(const vector&); + vector(const vector& other); + unsigned int size() const; bool empty() const; void clear(); @@ -71,7 +80,7 @@ namespace std { let array_to_vector v argcons array = for i = 0 to (Array.length array) - 1 do - (invoke v) "set" (C_list [ C_int i ; (argcons array.(i)) ]) + ignore ((invoke v) "set" (C_list [ C_int i ; (argcons array.(i)) ])) done ; v diff --git a/Lib/ocaml/stl.i b/Lib/ocaml/stl.i index 9d2e91eee..04f86014f 100644 --- a/Lib/ocaml/stl.i +++ b/Lib/ocaml/stl.i @@ -1,7 +1,5 @@ /* ----------------------------------------------------------------------------- * stl.i - * - * Initial STL definition. extended as needed in each language * ----------------------------------------------------------------------------- */ %include diff --git a/Lib/ocaml/swig.ml b/Lib/ocaml/swig.ml index 5dc2de7be..58a93347b 100644 --- a/Lib/ocaml/swig.ml +++ b/Lib/ocaml/swig.ml @@ -44,6 +44,13 @@ let _ = Callback.register "swig_runmethod" invoke let fnhelper arg = match arg with C_list l -> l | C_void -> [] | _ -> [ arg ] +let director_core_helper fnargs = + try + match List.hd fnargs with + | C_director_core (o,r) -> fnargs + | _ -> C_void :: fnargs + with Failure _ -> C_void :: fnargs + let rec get_int x = match x with C_bool b -> if b then 1 else 0 @@ -155,5 +162,5 @@ let _ = Callback.register "swig_set_type_info" set_type_info let class_master_list = Hashtbl.create 20 let register_class_byname nm co = Hashtbl.replace class_master_list nm (Obj.magic co) -let create_class nm arg = - try (Obj.magic (Hashtbl.find class_master_list nm)) arg with _ -> raise (NoSuchClass nm) +let create_class nm = + try (Obj.magic (Hashtbl.find class_master_list nm)) with _ -> raise (NoSuchClass nm) diff --git a/Lib/ocaml/swig.mli b/Lib/ocaml/swig.mli index 3207b9e73..c5ffadb15 100644 --- a/Lib/ocaml/swig.mli +++ b/Lib/ocaml/swig.mli @@ -30,6 +30,7 @@ exception NoSuchClass of string val invoke : ('a c_obj_t) -> (string -> 'a c_obj_t -> 'a c_obj_t) val fnhelper : 'a c_obj_t -> 'a c_obj_t list +val director_core_helper : 'a c_obj_t list -> 'a c_obj_t list val get_int : 'a c_obj_t -> int val get_float : 'a c_obj_t -> float diff --git a/Lib/ocaml/typecheck.i b/Lib/ocaml/typecheck.i index a13e1552e..0c0a600a0 100644 --- a/Lib/ocaml/typecheck.i +++ b/Lib/ocaml/typecheck.i @@ -4,7 +4,7 @@ * Typechecking rules * ----------------------------------------------------------------------------- */ -%typecheck(SWIG_TYPECHECK_INTEGER) char, signed char, const char &, const signed char & { +%typecheck(SWIG_TYPECHECK_INT8) char, signed char, const char &, const signed char & { if( !Is_block($input) ) $1 = 0; else { switch( SWIG_Tag_val($input) ) { @@ -14,7 +14,7 @@ } } -%typecheck(SWIG_TYPECHECK_INTEGER) unsigned char, const unsigned char & { +%typecheck(SWIG_TYPECHECK_UINT8) unsigned char, const unsigned char & { if( !Is_block($input) ) $1 = 0; else { switch( SWIG_Tag_val($input) ) { @@ -24,7 +24,7 @@ } } -%typecheck(SWIG_TYPECHECK_INTEGER) short, signed short, const short &, const signed short &, wchar_t { +%typecheck(SWIG_TYPECHECK_INT16) short, signed short, const short &, const signed short &, wchar_t { if( !Is_block($input) ) $1 = 0; else { switch( SWIG_Tag_val($input) ) { @@ -34,7 +34,7 @@ } } -%typecheck(SWIG_TYPECHECK_INTEGER) unsigned short, const unsigned short & { +%typecheck(SWIG_TYPECHECK_UINT16) unsigned short, const unsigned short & { if( !Is_block($input) ) $1 = 0; else { switch( SWIG_Tag_val($input) ) { @@ -47,7 +47,7 @@ // XXX arty // Will move enum SWIGTYPE later when I figure out what to do with it... -%typecheck(SWIG_TYPECHECK_INTEGER) int, signed int, const int &, const signed int &, enum SWIGTYPE { +%typecheck(SWIG_TYPECHECK_INT32) int, signed int, const int &, const signed int &, enum SWIGTYPE { if( !Is_block($input) ) $1 = 0; else { switch( SWIG_Tag_val($input) ) { @@ -57,7 +57,7 @@ } } -%typecheck(SWIG_TYPECHECK_INTEGER) unsigned int, const unsigned int & { +%typecheck(SWIG_TYPECHECK_UINT32) unsigned int, const unsigned int & { if( !Is_block($input) ) $1 = 0; else { switch( SWIG_Tag_val($input) ) { @@ -68,7 +68,13 @@ } } -%typecheck(SWIG_TYPECHECK_INTEGER) long, signed long, unsigned long, long long, signed long long, unsigned long long, const long &, const signed long &, const unsigned long &, const long long &, const signed long long &, const unsigned long long & { +%typecheck(SWIG_TYPECHECK_INT64) + long, signed long, unsigned long, + long long, signed long long, unsigned long long, + const long &, const signed long &, const unsigned long &, + const long long &, const signed long long &, const unsigned long long &, + size_t, const size_t & +{ if( !Is_block($input) ) $1 = 0; else { switch( SWIG_Tag_val($input) ) { @@ -78,7 +84,7 @@ } } -%typecheck(SWIG_TYPECHECK_INTEGER) bool, oc_bool, BOOL, const bool &, const oc_bool &, const BOOL & { +%typecheck(SWIG_TYPECHECK_BOOL) bool, const bool & { if( !Is_block($input) ) $1 = 0; else { switch( SWIG_Tag_val($input) ) { @@ -88,7 +94,7 @@ } } -%typecheck(SWIG_TYPECHECK_DOUBLE) float, const float & { +%typecheck(SWIG_TYPECHECK_FLOAT) float, const float & { if( !Is_block($input) ) $1 = 0; else { switch( SWIG_Tag_val($input) ) { @@ -130,24 +136,42 @@ } %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] { - void *ptr; - $1 = !caml_ptr_val_internal($input, &ptr,$descriptor); + if (!Is_block($input) || !(SWIG_Tag_val($input) == C_obj || SWIG_Tag_val($input) == C_ptr)) { + $1 = 0; + } else { + void *ptr; + $1 = !caml_ptr_val_internal($input, &ptr, $descriptor); + } } -#if 0 - %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { - void *ptr; - $1 = !caml_ptr_val_internal($input, &ptr, $&1_descriptor); + swig_type_info *typeinfo; + if (!Is_block($input)) { + $1 = 0; + } else { + switch (SWIG_Tag_val($input)) { + case C_obj: { + void *ptr; + $1 = !caml_ptr_val_internal($input, &ptr, $&1_descriptor); + break; + } + case C_ptr: { + typeinfo = (swig_type_info *)SWIG_Int64_val(SWIG_Field($input, 1)); + $1 = SWIG_TypeCheck("$1_type", typeinfo) != NULL; + break; + } + default: $1 = 0; break; + } + } } -#endif - %typecheck(SWIG_TYPECHECK_VOIDPTR) void * { void *ptr; $1 = !caml_ptr_val_internal($input, &ptr, 0); } +%typecheck(SWIG_TYPECHECK_SWIGOBJECT) CAML_VALUE "$1 = 1;" + /* ------------------------------------------------------------ * Exception handling * ------------------------------------------------------------ */ @@ -158,19 +182,16 @@ unsigned int, unsigned long, unsigned short { - SWIG_exception($1,"Thrown exception from C++ (int)"); + char error_msg[256]; + sprintf(error_msg, "C++ $1_type exception thrown, value: %d", $1); + SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, error_msg); } -%typemap(throws) SWIGTYPE CLASS { - $&1_ltype temp = new $1_ltype($1); - SWIG_exception((int)temp,"Thrown exception from C++ (object)"); -} - -%typemap(throws) SWIGTYPE { +%typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE *, SWIGTYPE [], SWIGTYPE [ANY] { (void)$1; - SWIG_exception(0,"Thrown exception from C++ (unknown)"); + SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, "C++ $1_type exception thrown"); } %typemap(throws) char * { - SWIG_exception(0,$1); + SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, $1); } diff --git a/Lib/ocaml/typemaps.i b/Lib/ocaml/typemaps.i index 7602ad629..39231e221 100644 --- a/Lib/ocaml/typemaps.i +++ b/Lib/ocaml/typemaps.i @@ -1,371 +1,44 @@ -/* ----------------------------------------------------------------------------- +/* ---------------------------------------------------------------------------- * typemaps.i * - * The Ocaml module handles all types uniformly via typemaps. Here - * are the definitions. - * ----------------------------------------------------------------------------- */ + * These typemaps provide support for input/output arguments for C/C++ pointers + * and C++ references. +* ---------------------------------------------------------------------------- */ -/* Pointers */ - -%typemap(in) void "" - -%typemap(out) void "$result = Val_int(0);" - -%typemap(in) void * { - $1 = caml_ptr_val($input,$descriptor); -} - -%typemap(varin) void * { - $1 = ($ltype)caml_ptr_val($input,$descriptor); -} - -%typemap(out) void * { - $result = caml_val_ptr($1,$descriptor); -} - -%typemap(varout) void * { - $result = caml_val_ptr($1,$descriptor); -} - -#ifdef __cplusplus - -%typemap(in) SWIGTYPE & { - /* %typemap(in) SWIGTYPE & */ - $1 = ($ltype) caml_ptr_val($input,$1_descriptor); -} - -%typemap(in) SWIGTYPE && { - /* %typemap(in) SWIGTYPE && */ - $1 = ($ltype) caml_ptr_val($input,$1_descriptor); -} - -%typemap(varin) SWIGTYPE & { - /* %typemap(varin) SWIGTYPE & */ - $1 = *(($ltype) caml_ptr_val($input,$1_descriptor)); -} - -%typemap(varin) SWIGTYPE && { - /* %typemap(varin) SWIGTYPE && */ - $1 = *(($ltype) caml_ptr_val($input,$1_descriptor)); -} - -%typemap(out) SWIGTYPE & { - /* %typemap(out) SWIGTYPE & */ - CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); - if( fromval ) { - $result = callback(*fromval,caml_val_ptr((void *) &$1,$1_descriptor)); - } else { - $result = caml_val_ptr ((void *) &$1,$1_descriptor); - } -} - -%typemap(out) SWIGTYPE && { - /* %typemap(out) SWIGTYPE && */ - CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); - if( fromval ) { - $result = callback(*fromval,caml_val_ptr((void *) &$1,$1_descriptor)); - } else { - $result = caml_val_ptr ((void *) &$1,$1_descriptor); - } -} - -#if 0 -%typemap(argout) SWIGTYPE & { - CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); - if( fromval ) { - swig_result = - caml_list_append(swig_result, - callback(*fromval,caml_val_ptr((void *) $1, - $1_descriptor))); - } else { - swig_result = - caml_list_append(swig_result, - caml_val_ptr ((void *) $1,$1_descriptor)); - } -} -%typemap(argout) SWIGTYPE && { - CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); - if( fromval ) { - swig_result = - caml_list_append(swig_result, - callback(*fromval,caml_val_ptr((void *) $1, - $1_descriptor))); - } else { - swig_result = - caml_list_append(swig_result, - caml_val_ptr ((void *) $1,$1_descriptor)); - } -} -#endif - -%typemap(argout) const SWIGTYPE & { } -%typemap(argout) const SWIGTYPE && { } - -%typemap(in) SWIGTYPE { - $1 = *(($&1_ltype) caml_ptr_val($input,$&1_descriptor)) ; -} - -%typemap(out) SWIGTYPE { - /* %typemap(out) SWIGTYPE */ - $&1_ltype temp = new $ltype((const $1_ltype &) $1); - CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); - if( fromval ) { - $result = callback(*fromval,caml_val_ptr((void *)temp,$&1_descriptor)); - } else { - $result = caml_val_ptr ((void *)temp,$&1_descriptor); - } -} - -%typemap(in) char *& (char *temp) { - /* %typemap(in) char *& */ - temp = (char*)caml_val_ptr($1,$descriptor); +%define INPUT_OUTPUT_INOUT_TYPEMAPS(type, c_to_ocaml, ocaml_to_c) +%typemap(in) type *INPUT(type temp), type &INPUT(type temp) { + temp = (type)ocaml_to_c($input); $1 = &temp; } +%typemap(typecheck) type *INPUT = type; +%typemap(typecheck) type &INPUT = type; -%typemap(argout) char *& { - /* %typemap(argout) char *& */ - swig_result = caml_list_append(swig_result,caml_val_string_len(*$1, strlen(*$1))); +%typemap(in, numinputs=0) type *OUTPUT($*1_ltype temp), type &OUTPUT($*1_ltype temp) "$1 = &temp;" +%typemap(argout) type *OUTPUT, type &OUTPUT { + swig_result = caml_list_append(swig_result, c_to_ocaml(*$1)); } +%typemap(in) type *INOUT = type *INPUT; +%typemap(in) type &INOUT = type &INPUT; -#else +%typemap(argout) type *INOUT = type *OUTPUT; +%typemap(argout) type &INOUT = type &OUTPUT; -%typemap(in) SWIGTYPE { - $1 = *(($&1_ltype) caml_ptr_val($input,$&1_descriptor)) ; -} - -%typemap(out) SWIGTYPE { - /* %typemap(out) SWIGTYPE */ - void *temp = calloc(1,sizeof($ltype)); - CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); - memmove( temp, &$1, sizeof( $1_type ) ); - if( fromval ) { - $result = callback(*fromval,caml_val_ptr((void *)temp,$&1_descriptor)); - } else { - $result = caml_val_ptr ((void *)temp,$&1_descriptor); - } -} - -%apply SWIGTYPE { const SWIGTYPE & }; -%apply SWIGTYPE { const SWIGTYPE && }; - -#endif - -/* The SIMPLE_MAP macro below defines the whole set of typemaps needed - for simple types. */ - -%define SIMPLE_MAP(C_NAME, C_TO_MZ, MZ_TO_C) -/* In */ -%typemap(in) C_NAME { - $1 = MZ_TO_C($input); -} -%typemap(varin) C_NAME { - $1 = MZ_TO_C($input); -} -%typemap(in) C_NAME & ($*1_ltype temp) { - temp = ($*1_ltype) MZ_TO_C($input); - $1 = &temp; -} -%typemap(varin) C_NAME & { - $1 = MZ_TO_C($input); -} -%typemap(directorout) C_NAME { - $1 = MZ_TO_C($input); -} -%typemap(in) C_NAME *INPUT ($*1_ltype temp) { - temp = ($*1_ltype) MZ_TO_C($input); - $1 = &temp; -} -%typemap(in,numinputs=0) C_NAME *OUTPUT ($*1_ltype temp) { - $1 = &temp; -} -/* Out */ -%typemap(out) C_NAME { - $result = C_TO_MZ($1); -} -%typemap(varout) C_NAME { - $result = C_TO_MZ($1); -} -%typemap(varout) C_NAME & { - /* %typemap(varout) C_NAME & (generic) */ - $result = C_TO_MZ($1); -} -%typemap(argout) C_NAME *OUTPUT { - swig_result = caml_list_append(swig_result,C_TO_MZ((long)*$1)); -} -%typemap(out) C_NAME & { - /* %typemap(out) C_NAME & (generic) */ - $result = C_TO_MZ(*$1); -} -%typemap(argout) C_NAME & { - swig_result = caml_list_append(swig_result,C_TO_MZ((long)*$1)); -} -%typemap(directorin) C_NAME { - args = caml_list_append(args,C_TO_MZ($1)); -} +%typemap(typecheck) type *INOUT = type; +%typemap(typecheck) type &INOUT = type; %enddef -SIMPLE_MAP(bool, caml_val_bool, caml_long_val); -SIMPLE_MAP(oc_bool, caml_val_bool, caml_long_val); -SIMPLE_MAP(char, caml_val_char, caml_long_val); -SIMPLE_MAP(signed char, caml_val_char, caml_long_val); -SIMPLE_MAP(unsigned char, caml_val_uchar, caml_long_val); -SIMPLE_MAP(int, caml_val_int, caml_long_val); -SIMPLE_MAP(short, caml_val_short, caml_long_val); -SIMPLE_MAP(wchar_t, caml_val_short, caml_long_val); -SIMPLE_MAP(long, caml_val_long, caml_long_val); -SIMPLE_MAP(ptrdiff_t, caml_val_int, caml_long_val); -SIMPLE_MAP(unsigned int, caml_val_uint, caml_long_val); -SIMPLE_MAP(unsigned short, caml_val_ushort, caml_long_val); -SIMPLE_MAP(unsigned long, caml_val_ulong, caml_long_val); -SIMPLE_MAP(size_t, caml_val_int, caml_long_val); -SIMPLE_MAP(float, caml_val_float, caml_double_val); -SIMPLE_MAP(double, caml_val_double, caml_double_val); -SIMPLE_MAP(long long,caml_val_ulong,caml_long_val); -SIMPLE_MAP(unsigned long long,caml_val_ulong,caml_long_val); - -/* Void */ - -%typemap(out) void "$result = Val_unit;"; - -/* Pass through value */ - -%typemap (in) value,caml::value,CAML_VALUE "$1=$input;"; -%typemap (out) value,caml::value,CAML_VALUE "$result=$1;"; - -/* Arrays */ - -%typemap(in) ArrayCarrier * { - $1 = ($ltype)caml_ptr_val($input,$1_descriptor); -} - -%typemap(out) ArrayCarrier * { - CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); - if( fromval ) { - $result = callback(*fromval,caml_val_ptr((void *)$1,$1_descriptor)); - } else { - $result = caml_val_ptr ((void *)$1,$1_descriptor); - } -} - -#if 0 -%include -#endif - -/* Handle char arrays as strings */ - -%define %char_ptr_in(how) -%typemap(how) char *, signed char *, unsigned char * { - /* %typemap(how) char * ... */ - $1 = ($ltype)caml_string_val($input); -} -/* Again work around the empty array bound bug */ -%typemap(how) char [ANY], signed char [ANY], unsigned char [ANY] { - /* %typemap(how) char [ANY] ... */ - char *temp = caml_string_val($input); - strcpy((char *)$1,temp); - /* strncpy would be better but we might not have an array size */ -} -%enddef - -%char_ptr_in(in); -%char_ptr_in(varin); -%char_ptr_in(directorout); - -%define %char_ptr_out(how) -%typemap(how) - char *, signed char *, unsigned char *, - const char *, const signed char *, const unsigned char * { - $result = caml_val_string((char *)$1); -} -/* I'd like to use the length here but can't because it might be empty */ -%typemap(how) - char [ANY], signed char [ANY], unsigned char [ANY], - const char [ANY], const signed char [ANY], const unsigned char [ANY] { - $result = caml_val_string((char *)$1); -} -%enddef - -%char_ptr_out(out); -%char_ptr_out(varout); -%char_ptr_out(directorin); - -%define %swigtype_ptr_in(how) -%typemap(how) SWIGTYPE * { - /* %typemap(how) SWIGTYPE * */ - $1 = ($ltype)caml_ptr_val($input,$1_descriptor); -} -%typemap(how) SWIGTYPE (CLASS::*) { - /* %typemap(how) SWIGTYPE (CLASS::*) */ - void *v = caml_ptr_val($input,$1_descriptor); - memcpy(& $1, &v, sizeof(v)); -} -%enddef - -%define %swigtype_ptr_out(how) -%typemap(out) SWIGTYPE * { - /* %typemap(how) SWIGTYPE *, SWIGTYPE (CLASS::*) */ - CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr"); - if( fromval ) { - $result = callback(*fromval,caml_val_ptr((void *)$1,$1_descriptor)); - } else { - $result = caml_val_ptr ((void *)$1,$1_descriptor); - } -} -%typemap(how) SWIGTYPE (CLASS::*) { - /* %typemap(how) SWIGTYPE *, SWIGTYPE (CLASS::*) */ - void *v; - memcpy(&v,& $1, sizeof(void *)); - $result = caml_val_ptr (v,$1_descriptor); -} -%enddef - -%swigtype_ptr_in(in); -%swigtype_ptr_in(varin); -%swigtype_ptr_in(directorout); -%swigtype_ptr_out(out); -%swigtype_ptr_out(varout); -%swigtype_ptr_out(directorin); - -%define %swigtype_array_fail(how,msg) -%typemap(how) SWIGTYPE [] { - failwith(msg); -} -%enddef - -%swigtype_array_fail(in,"Array arguments for arbitrary types need a typemap"); -%swigtype_array_fail(varin,"Assignment to global arrays for arbitrary types need a typemap"); -%swigtype_array_fail(out,"Array arguments for arbitrary types need a typemap"); -%swigtype_array_fail(varout,"Array variables need a typemap"); -%swigtype_array_fail(directorin,"Array results with arbitrary types need a typemap"); -%swigtype_array_fail(directorout,"Array arguments with arbitrary types need a typemap"); - -/* C++ References */ - -/* Enums */ -%define %swig_enum_in(how) -%typemap(how) enum SWIGTYPE { - $1 = ($type)caml_long_val_full($input,"$type_marker"); -} -%enddef - -%define %swig_enum_out(how) -%typemap(how) enum SWIGTYPE { - $result = callback2(*caml_named_value(SWIG_MODULE "_int_to_enum"),*caml_named_value("$type_marker"),Val_int((int)$1)); -} -%enddef - -%swig_enum_in(in) -%swig_enum_in(varin) -%swig_enum_in(directorout) -%swig_enum_out(out) -%swig_enum_out(varout) -%swig_enum_out(directorin) - - -/* Array reference typemaps */ -%apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } -%apply SWIGTYPE && { SWIGTYPE ((&)[ANY]) } - -/* const pointers */ -%apply SWIGTYPE * { SWIGTYPE *const } - +INPUT_OUTPUT_INOUT_TYPEMAPS(bool, caml_val_bool, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(int, caml_val_int, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(long, caml_val_long, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(short, caml_val_int, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(char, caml_val_char, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(signed char, caml_val_char, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(float, caml_val_float, caml_double_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(double, caml_val_double, caml_double_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(unsigned int, caml_val_uint, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(unsigned long, caml_val_ulong, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(unsigned short, caml_val_ushort, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(unsigned char, caml_val_uchar, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(long long, caml_val_long, caml_long_val); +INPUT_OUTPUT_INOUT_TYPEMAPS(unsigned long long, caml_val_ulong, caml_long_val); +#undef INPUT_OUTPUT_INOUT_TYPEMAPS diff --git a/Lib/octave/boost_shared_ptr.i b/Lib/octave/boost_shared_ptr.i index e91862057..668bf4354 100644 --- a/Lib/octave/boost_shared_ptr.i +++ b/Lib/octave/boost_shared_ptr.i @@ -1,5 +1,11 @@ %include +// Set SHARED_PTR_DISOWN to $disown if required, for example +// #define SHARED_PTR_DISOWN $disown +#if !defined(SHARED_PTR_DISOWN) +#define SHARED_PTR_DISOWN 0 +#endif + // Language specific macro implementing all the customisations for handling the smart pointer %define SWIG_SHARED_PTR_TYPEMAPS(CONST, TYPE...) @@ -8,7 +14,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor wrapper customisation -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -19,7 +25,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); @@ -52,13 +58,31 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) { + int newmem = 0; + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res, "$type"); + } + if (!swig_argp) { + %dirout_nullref("$type"); + } else { + $result = *(%reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get()); + if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); + } +} + // plain pointer -// Note: $disown not implemented as it will lead to a memory leak of the shared_ptr instance +// Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance %typemap(in) CONST TYPE * (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) { int newmem = 0; - res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -69,6 +93,7 @@ $1 = %const_cast((smartarg ? smartarg->get() : 0), $1_ltype); } } + %typemap(out, fragment="SWIG_null_deleter") CONST TYPE * { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), $owner | SWIG_POINTER_OWN)); @@ -97,12 +122,20 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE * %{ +#error "directorout typemap for plain pointer not implemented" +%} + // plain reference %typemap(in) CONST TYPE & (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { @@ -142,13 +175,21 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") CONST TYPE & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(&$1 SWIG_NO_NULL_DELETER_0); + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE & %{ +#error "directorout typemap for plain reference not implemented" +%} + // plain pointer by reference -// Note: $disown not implemented as it will lead to a memory leak of the shared_ptr instance +// Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance %typemap(in) TYPE *CONST& (void *argp = 0, int res = 0, $*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { int newmem = 0; - res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -160,7 +201,7 @@ $1 = &temp; } %typemap(out, fragment="SWIG_null_deleter") TYPE *CONST& { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -171,12 +212,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") TYPE *CONST& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) TYPE *CONST& %{ +#error "directorout typemap for plain pointer by reference not implemented" +%} + // shared_ptr by value %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *argp, int res = 0) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) $1 = *(%reinterpret_cast(argp, $<ype)); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $<ype); @@ -201,12 +250,28 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *swig_argp, int swig_res = 0) { + int newmem = 0; + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res, "$type"); + } + if (swig_argp) { + $result = *(%reinterpret_cast(swig_argp, $<ype)); + if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, $<ype); + } +} + // shared_ptr by reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (void *argp, int res = 0, $*1_ltype tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -228,12 +293,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{ +#error "directorout typemap for shared_ptr ref not implemented" +%} + // shared_ptr by pointer %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (void *argp, int res = 0, $*1_ltype tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -244,7 +317,7 @@ } } %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 && *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); if ($owner) delete $1; } @@ -256,12 +329,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{ +#error "directorout typemap for pointer to shared_ptr not implemented" +%} + // shared_ptr by pointer reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (void *argp, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, $*1_ltype temp = 0) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) tempshared = *%reinterpret_cast(argp, $*ltype); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $*ltype); @@ -269,7 +350,7 @@ $1 = &temp; } %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 && **$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -280,10 +361,18 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{ +#error "directorout typemap for pointer ref to shared_ptr not implemented" +%} + // Typecheck typemaps -// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting +// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, @@ -307,5 +396,6 @@ %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; -%enddef + +%enddef diff --git a/Lib/octave/director.swg b/Lib/octave/director.swg index e80877ef6..bf71d18e8 100644 --- a/Lib/octave/director.swg +++ b/Lib/octave/director.swg @@ -46,10 +46,12 @@ namespace Swig { } }; - struct DirectorTypeMismatchException { + // Base class for director exceptions. + class DirectorException : public std::exception { + public: static void raise(const char *msg) { // ... todo - throw(DirectorTypeMismatchException()); + throw DirectorException(); } static void raise(const octave_value &ov, const char *msg) { @@ -58,10 +60,24 @@ namespace Swig { } }; - struct DirectorPureVirtualException { + class DirectorTypeMismatchException : public DirectorException { + public: static void raise(const char *msg) { // ... todo - throw(DirectorPureVirtualException()); + throw DirectorTypeMismatchException(); + } + + static void raise(const octave_value &ov, const char *msg) { + // ... todo + raise(msg); + } + }; + + class DirectorPureVirtualException : public DirectorException { + public: + static void raise(const char *msg) { + // ... todo + throw DirectorPureVirtualException(); } static void raise(const octave_value &ov, const char *msg) { diff --git a/Lib/octave/exception.i b/Lib/octave/exception.i index bb0b15c9d..2f0f489aa 100644 --- a/Lib/octave/exception.i +++ b/Lib/octave/exception.i @@ -1,6 +1,14 @@ %include - %insert("runtime") { %define_as(SWIG_exception(code, msg), %block(%error(code, msg); SWIG_fail; )) } + +%define SWIG_RETHROW_OCTAVE_EXCEPTIONS + /* rethrow any exceptions thrown by Octave */ +%#if SWIG_OCTAVE_PREREQ(4,2,0) + catch (octave::execution_exception& _e) { throw; } + catch (octave::exit_exception& _e) { throw; } + catch (octave::interrupt_exception& _e) { throw; } +%#endif +%enddef diff --git a/Lib/octave/octcontainer.swg b/Lib/octave/octcontainer.swg index af58f3aaa..269ff7544 100644 --- a/Lib/octave/octcontainer.swg +++ b/Lib/octave/octcontainer.swg @@ -68,7 +68,7 @@ namespace swig { namespace std { template <> - struct less : public binary_function + struct less { bool operator()(const octave_value& v, const octave_value& w) const @@ -202,8 +202,8 @@ namespace swig // swig::SwigVar_PyObject item = OctSequence_GetItem(_seq, _index); octave_value item; // * todo try { - return swig::as(item, true); - } catch (std::exception& e) { + return swig::as(item); + } catch (const std::exception& e) { char msg[1024]; sprintf(msg, "in sequence element %d ", _index); if (!Octave_Error_Occurred()) { @@ -567,7 +567,11 @@ namespace swig { if (seq) *seq = p; return SWIG_OLDOBJ; } +%#if SWIG_OCTAVE_PREREQ(4,4,0) + } else if (obj.iscell()) { +%#else } else if (obj.is_cell()) { +%#endif try { OctSequence_Cont octseq(obj); if (seq) { diff --git a/Lib/octave/octiterators.swg b/Lib/octave/octiterators.swg index 79a20f833..e186c94a2 100644 --- a/Lib/octave/octiterators.swg +++ b/Lib/octave/octiterators.swg @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- * octiterators.swg * - * Users can derive form the OctSwigIterator to implemet their + * Users can derive form the OctSwigIterator to implement their * own iterators. As an example (real one since we use it for STL/STD * containers), the template OctSwigIterator_T does the * implementation for generic C++ iterators. diff --git a/Lib/octave/octopers.swg b/Lib/octave/octopers.swg index c38e64d8c..665b7033d 100644 --- a/Lib/octave/octopers.swg +++ b/Lib/octave/octopers.swg @@ -25,8 +25,6 @@ // __div__ a / b // __pow__ a ^ b // __ldiv__ a \ b -// __lshift__ a << b -// __rshift__ a >> b // __lt__ a < b // __le__ a <= b // __eq__ a == b @@ -51,8 +49,6 @@ %rename(__mul__) *::operator*; %rename(__div__) *::operator/; %rename(__mod__) *::operator%; -%rename(__lshift__) *::operator<<; -%rename(__rshift__) *::operator>>; %rename(__el_and__) *::operator&&; %rename(__el_or__) *::operator||; %rename(__xor__) *::operator^; @@ -84,5 +80,7 @@ // Ignored operators %ignoreoperator(EQ) operator=; %ignoreoperator(ARROWSTAR) operator->*; +%ignoreoperator(LSHIFT) operator<<; +%ignoreoperator(RSHIFT) operator>>; #endif /* __cplusplus */ diff --git a/Lib/octave/octprimtypes.swg b/Lib/octave/octprimtypes.swg index 663d1fe10..1c9aa9089 100644 --- a/Lib/octave/octprimtypes.swg +++ b/Lib/octave/octprimtypes.swg @@ -18,7 +18,11 @@ SWIGINTERNINLINE octave_value SWIGINTERN int SWIG_AsVal_dec(bool)(const octave_value& ov, bool *val) { +%#if SWIG_OCTAVE_PREREQ(4,4,0) + if (!ov.islogical()) +%#else if (!ov.is_bool_type()) +%#endif return SWIG_ERROR; if (val) *val = ov.bool_value(); @@ -214,7 +218,13 @@ SWIG_AsVal_dec(bool)(const octave_value& ov, bool *val) SWIGINTERN int SWIG_AsCharPtrAndSize(octave_value ov, char** cptr, size_t* psize, int *alloc) { - if (ov.is_cell() && ov.rows() == 1 && ov.columns() == 1) + if ( +%#if SWIG_OCTAVE_PREREQ(4,4,0) + ov.iscell() +%#else + ov.is_cell() +%#endif + && ov.rows() == 1 && ov.columns() == 1) ov = ov.cell_value()(0); if (!ov.is_string()) return SWIG_TypeError; diff --git a/Lib/octave/octrun.swg b/Lib/octave/octrun.swg index c1c0dcd67..ff614e681 100644 --- a/Lib/octave/octrun.swg +++ b/Lib/octave/octrun.swg @@ -1,87 +1,3 @@ - -#include - -// Macro for enabling features which require Octave version >= major.minor.patch -#define SWIG_OCTAVE_PREREQ(major, minor, patch) \ - ( (OCTAVE_MAJOR_VERSION<<16) + (OCTAVE_MINOR_VERSION<<8) + OCTAVE_PATCH_VERSION >= ((major)<<16) + ((minor)<<8) + (patch) ) - -// Reconstruct Octave major, minor, and patch versions for releases prior to 3.8.1 -#if !defined(OCTAVE_MAJOR_VERSION) - -# if !defined(OCTAVE_API_VERSION_NUMBER) - -// Hack to distinguish between Octave 3.8.0, which removed OCTAVE_API_VERSION_NUMBER but did not yet -// introduce OCTAVE_MAJOR_VERSION, and Octave <= 3.2, which did not define OCTAVE_API_VERSION_NUMBER -# include -# if defined(octave_ov_h) -# define OCTAVE_MAJOR_VERSION 3 -# define OCTAVE_MINOR_VERSION 8 -# define OCTAVE_PATCH_VERSION 0 -# else - -// Hack to distinguish between Octave 3.2 and earlier versions, before OCTAVE_API_VERSION_NUMBER existed -# define ComplexLU __ignore -# include -# undef ComplexLU -# if defined(octave_Complex_LU_h) - -// We know only that this version is prior to Octave 3.2, i.e. OCTAVE_API_VERSION_NUMBER < 37 -# define OCTAVE_MAJOR_VERSION 3 -# define OCTAVE_MINOR_VERSION 1 -# define OCTAVE_PATCH_VERSION 99 - -# else - -// OCTAVE_API_VERSION_NUMBER == 37 -# define OCTAVE_MAJOR_VERSION 3 -# define OCTAVE_MINOR_VERSION 2 -# define OCTAVE_PATCH_VERSION 0 - -# endif // defined(octave_Complex_LU_h) - -# endif // defined(octave_ov_h) - -// Correlation between Octave API and version numbers extracted from Octave's -// ChangeLogs; version is the *earliest* released Octave with that API number -# elif OCTAVE_API_VERSION_NUMBER >= 48 -# define OCTAVE_MAJOR_VERSION 3 -# define OCTAVE_MINOR_VERSION 6 -# define OCTAVE_PATCH_VERSION 0 - -# elif OCTAVE_API_VERSION_NUMBER >= 45 -# define OCTAVE_MAJOR_VERSION 3 -# define OCTAVE_MINOR_VERSION 4 -# define OCTAVE_PATCH_VERSION 1 - -# elif OCTAVE_API_VERSION_NUMBER >= 42 -# define OCTAVE_MAJOR_VERSION 3 -# define OCTAVE_MINOR_VERSION 3 -# define OCTAVE_PATCH_VERSION 54 - -# elif OCTAVE_API_VERSION_NUMBER >= 41 -# define OCTAVE_MAJOR_VERSION 3 -# define OCTAVE_MINOR_VERSION 3 -# define OCTAVE_PATCH_VERSION 53 - -# elif OCTAVE_API_VERSION_NUMBER >= 40 -# define OCTAVE_MAJOR_VERSION 3 -# define OCTAVE_MINOR_VERSION 3 -# define OCTAVE_PATCH_VERSION 52 - -# elif OCTAVE_API_VERSION_NUMBER >= 39 -# define OCTAVE_MAJOR_VERSION 3 -# define OCTAVE_MINOR_VERSION 3 -# define OCTAVE_PATCH_VERSION 51 - -# else // OCTAVE_API_VERSION_NUMBER == 38 -# define OCTAVE_MAJOR_VERSION 3 -# define OCTAVE_MINOR_VERSION 3 -# define OCTAVE_PATCH_VERSION 50 - -# endif // !defined(OCTAVE_API_VERSION_NUMBER) - -#endif // !defined(OCTAVE_MAJOR_VERSION) - #if !SWIG_OCTAVE_PREREQ(3,2,0) #define SWIG_DEFUN(cname, wname, doc) DEFUNX_DLD(#cname, wname, FS ## cname, args, nargout, doc) #else @@ -135,7 +51,7 @@ SWIGRUNTIME octave_value SWIG_Error(int code, const char *msg) { octave_value type(SWIG_ErrorType(code)); std::string r = msg; r += " (" + type.string_value() + ")"; - error(r.c_str()); + error("%s", r.c_str()); return octave_value(r); } @@ -235,6 +151,67 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); const swig_type_info **base; }; +#if SWIG_OCTAVE_PREREQ(4,4,0) + // in Octave 4.4 behaviour of octave_builtin() appears to have changed and 'self' argument is no longer passed + // to function (maybe because this is now a 'method'??) so need to create our own octave_function subclass +#define SWIG_OCTAVE_BOUND_FUNC(func, args) octave_value(new octave_swig_bound_func(func, args)) + class octave_swig_bound_func : public octave_function { + public: + + octave_swig_bound_func(void) : octave_function(), method(0), first_args() + { } + + octave_swig_bound_func(octave_function* _method, octave_value_list _first_args) + : octave_function("", ""), method(_method), first_args(_first_args) + { } + + octave_swig_bound_func(const octave_swig_bound_func& f) = delete; + + octave_swig_bound_func& operator= (const octave_swig_bound_func& f) = delete; + + ~octave_swig_bound_func(void) = default; + + bool is_function(void) const { return true; } + + octave_function* function_value(bool = false) { return this; } + + octave_value_list call(octave::tree_evaluator& tw, int nargout = 0, const octave_value_list& args = octave_value_list()) { + octave_value_list all_args; + all_args.append(first_args); + all_args.append(args); + return method->call(tw, nargout, all_args); + } + + octave_value subsref(const std::string &ops, const std::list < octave_value_list > &idx) { + octave_value_list ovl = subsref(ops, idx, 1); + return ovl.length() ? ovl(0) : octave_value(); + } + + octave_value_list subsref(const std::string &ops, const std::list < octave_value_list > &idx, int nargout) { + assert(ops.size() > 0); + assert(ops.size() == idx.size()); + if (ops != "(") + error("invalid function call"); + octave::tree_evaluator& tw = octave::interpreter::the_interpreter()->get_evaluator(); + return call(tw, nargout, *idx.begin()); + } + + protected: + + octave_function* method; + octave_value_list first_args; + + std::set dispatch_classes; + + private: + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA + }; + DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_swig_bound_func, "octave_swig_bound_func", "octave_swig_bound_func"); +#else +#define SWIG_OCTAVE_BOUND_FUNC(func, args) octave_value(func) +#endif + // octave_swig_type plays the role of both the shadow class and the class // representation within Octave, since there is no support for classes. // @@ -407,13 +384,17 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); } octave_value_list member_deref(member_value_pair *m, const octave_value_list &args) { - if (m->second.is_defined()) - return m->second; - else if (m->first) { + if (m->second.is_defined()) { + if (m->second.is_function() || m->second.is_function_handle()) { + return SWIG_OCTAVE_BOUND_FUNC(m->second.function_value(), args); + } else { + return m->second; + } + } else if (m->first) { if (m->first->get_method) return m->first->get_method(args, 1); else if (m->first->method) - return octave_value(new octave_builtin(m->first->method)); + return SWIG_OCTAVE_BOUND_FUNC(new octave_builtin(m->first->method), args); } error("undefined member"); return octave_value_list(); @@ -467,7 +448,11 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); return dim_vector(1,1); // Return value should be cell or matrix of integers +#if SWIG_OCTAVE_PREREQ(4,4,0) + if (out.iscell()) { +#else if (out.is_cell()) { +#endif const Cell & c=out.cell_value(); int ndim = c.rows(); if (ndim==1 && c.columns()!=1) ndim = c.columns(); @@ -485,7 +470,11 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); if (error_state) return dim_vector(1,1); } return d; +#if SWIG_OCTAVE_PREREQ(4,4,0) + } else if (out.is_matrix_type() || out.isnumeric() ) { +#else } else if (out.is_matrix_type() || out.is_numeric_type() ) { +#endif if (out.rows()==1 || out.columns()==1) { Array a = out.int_vector_value(); if (error_state) return dim_vector(1,1); @@ -560,8 +549,12 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); } types.insert(types.end(), rhs.types.begin(), rhs.types.end()); members.insert(rhs.members.begin(), rhs.members.end()); +#if SWIG_OCTAVE_PREREQ(4,4,0) + assign(rhs.swig_type_name(), rhs.as_value()); +#else rhs.types.clear(); rhs.members.clear(); +#endif } typedef member_map::const_iterator swig_member_const_iterator; @@ -824,12 +817,30 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); return ret.scalar_value(); } +#if SWIG_OCTAVE_PREREQ(4,2,0) + virtual octave_value as_double(void) const { + octave_value ret; + if (!dispatch_unary_op("__float__", ret)) { + error("__float__ method not defined"); + } + return ret.as_double(); + } + + virtual octave_value as_single(void) const { + octave_value ret; + if (!dispatch_unary_op("__float__", ret)) { + error("__float__ method not defined"); + } + return ret.as_single(); + } +#endif + #if SWIG_OCTAVE_PREREQ(3,8,0) virtual octave_value map(octave_base_value::unary_mapper_t umap) const { const std::string opname = std::string("__") + octave_base_value::get_umap_name(umap) + std::string("__"); octave_value ret; if (!dispatch_unary_op(opname, ret)) { - error((opname + std::string(" method not found")).c_str()); + error("%s", (opname + std::string(" method not found")).c_str()); return octave_value(); } return ret; @@ -914,7 +925,14 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); octave_function *fcn = is_valid_function(symbol, std::string(), false); if (!fcn) return false; +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::tree_evaluator& tw = octave::interpreter::the_interpreter()->get_evaluator(); + octave_value_list retval = fcn->call(tw, 1, args); + if (retval.length() == 1) + ret = retval(0); +#else ret = fcn->do_multi_index_op(1, args)(0); +#endif return true; } @@ -1092,6 +1110,14 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); virtual double scalar_value(bool frc_str_conv = false) const { return ptr->scalar_value(frc_str_conv); } +#if SWIG_OCTAVE_PREREQ(4,2,0) + virtual octave_value as_double(void) const + { return ptr->as_double(); } + + virtual octave_value as_single(void) const + { return ptr->as_single(); } +#endif + #if SWIG_OCTAVE_PREREQ(3,8,0) virtual octave_value map(octave_base_value::unary_mapper_t umap) const { return ptr->map(umap); } @@ -1296,7 +1322,13 @@ namespace Swig { } SWIGRUNTIME octave_swig_type *swig_value_deref(octave_value ov) { - if (ov.is_cell() && ov.rows() == 1 && ov.columns() == 1) + if ( +#if SWIG_OCTAVE_PREREQ(4,4,0) + ov.iscell() +#else + ov.is_cell() +#endif + && ov.rows() == 1 && ov.columns() == 1) ov = ov.cell_value()(0); return swig_value_deref(*ov.internal_rep()); } @@ -1319,12 +1351,24 @@ SWIGRUNTIME octave_value swig_unary_op_##name(const octave_base_value &x) { \ SWIGRUNTIME octave_value swig_binary_op_##name(const octave_base_value&lhs,const octave_base_value &rhs) { \ return octave_swig_type::dispatch_binary_op(lhs,rhs,#name); \ } +#if SWIG_OCTAVE_PREREQ(4,4,0) +#define swigreg_unary_op(name) \ +if (!octave_value_typeinfo::lookup_unary_op(octave_value::op_##name,tid)) \ +typeinfo.register_unary_op(octave_value::op_##name,tid,swig_unary_op_##name); +#else #define swigreg_unary_op(name) \ if (!octave_value_typeinfo::lookup_unary_op(octave_value::op_##name,tid)) \ octave_value_typeinfo::register_unary_op(octave_value::op_##name,tid,swig_unary_op_##name); +#endif +#if SWIG_OCTAVE_PREREQ(4,4,0) +#define swigreg_binary_op(name) \ +if (!octave_value_typeinfo::lookup_binary_op(octave_value::op_##name,tid1,tid2)) \ +typeinfo.register_binary_op(octave_value::op_##name,tid1,tid2,swig_binary_op_##name); +#else #define swigreg_binary_op(name) \ if (!octave_value_typeinfo::lookup_binary_op(octave_value::op_##name,tid1,tid2)) \ octave_value_typeinfo::register_binary_op(octave_value::op_##name,tid1,tid2,swig_binary_op_##name); +#endif swig_unary_op(not); swig_unary_op(uplus); @@ -1340,8 +1384,10 @@ octave_value_typeinfo::register_binary_op(octave_value::op_##name,tid1,tid2,swig swig_binary_op(div); swig_binary_op(pow); swig_binary_op(ldiv); +#if !SWIG_OCTAVE_PREREQ(4,2,0) swig_binary_op(lshift); swig_binary_op(rshift); +#endif swig_binary_op(lt); swig_binary_op(le); swig_binary_op(eq); @@ -1356,6 +1402,9 @@ octave_value_typeinfo::register_binary_op(octave_value::op_##name,tid1,tid2,swig swig_binary_op(el_or); SWIGRUNTIME void SWIG_InstallUnaryOps(int tid) { +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::type_info& typeinfo = octave::interpreter::the_interpreter()->get_type_info(); +#endif swigreg_unary_op(not); swigreg_unary_op(uplus); swigreg_unary_op(uminus); @@ -1365,14 +1414,19 @@ octave_value_typeinfo::register_binary_op(octave_value::op_##name,tid1,tid2,swig swigreg_unary_op(decr); } SWIGRUNTIME void SWIG_InstallBinaryOps(int tid1, int tid2) { +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::type_info& typeinfo = octave::interpreter::the_interpreter()->get_type_info(); +#endif swigreg_binary_op(add); swigreg_binary_op(sub); swigreg_binary_op(mul); swigreg_binary_op(div); swigreg_binary_op(pow); swigreg_binary_op(ldiv); +#if !SWIG_OCTAVE_PREREQ(4,2,0) swigreg_binary_op(lshift); swigreg_binary_op(rshift); +#endif swigreg_binary_op(lt); swigreg_binary_op(le); swigreg_binary_op(eq); @@ -1411,13 +1465,19 @@ SWIGRUNTIME octave_value SWIG_Octave_NewPointerObj(void *ptr, swig_type_info *ty } SWIGRUNTIME int SWIG_Octave_ConvertPtrAndOwn(octave_value ov, void **ptr, swig_type_info *type, int flags, int *own) { - if (ov.is_cell() && ov.rows() == 1 && ov.columns() == 1) + if ( +#if SWIG_OCTAVE_PREREQ(4,4,0) + ov.iscell() +#else + ov.is_cell() +#endif + && ov.rows() == 1 && ov.columns() == 1) ov = ov.cell_value()(0); if (!ov.is_defined() || (ov.is_matrix_type() && ov.rows() == 0 && ov.columns() == 0) ) { if (ptr) *ptr = 0; - return SWIG_OK; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } if (ov.type_id() != octave_swig_ref::static_type_id()) return SWIG_ERROR; @@ -1444,14 +1504,30 @@ SWIGRUNTIMEINLINE void SWIG_Octave_SetConstant(octave_swig_type *module_ns, cons } SWIGRUNTIMEINLINE octave_value SWIG_Octave_GetGlobalValue(std::string name) { +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::symbol_table& symtab = octave::interpreter::the_interpreter()->get_symbol_table(); + return symtab.global_varval(name); +#else return get_global_value(name, true); +#endif } SWIGRUNTIME void SWIG_Octave_SetGlobalValue(std::string name, const octave_value& value) { +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::symbol_table& symtab = octave::interpreter::the_interpreter()->get_symbol_table(); + symtab.global_assign(name, value); +#else set_global_value(name, value); +#endif } SWIGRUNTIME void SWIG_Octave_LinkGlobalValue(std::string name) { +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::symbol_table& symtab = octave::interpreter::the_interpreter()->get_symbol_table(); + octave::symbol_scope symscope = octave::interpreter::the_interpreter()->get_current_scope(); + symscope.assign(name, symtab.global_varval(name)); + symscope.mark_global(name); +#else #if !SWIG_OCTAVE_PREREQ(3,2,0) link_to_global_variable(curr_sym_tab->lookup(name, true)); #else @@ -1460,6 +1536,7 @@ SWIGRUNTIME void SWIG_Octave_LinkGlobalValue(std::string name) { #endif symbol_table::mark_global(name); #endif +#endif } SWIGRUNTIME swig_module_info *SWIG_Octave_GetModule(void *clientdata) { diff --git a/Lib/octave/octruntime.swg b/Lib/octave/octruntime.swg index 1efc96f8f..f98bf4fe4 100644 --- a/Lib/octave/octruntime.swg +++ b/Lib/octave/octruntime.swg @@ -1,7 +1,93 @@ %insert(runtime) %{ + #include #include + #include +#include + +// Macro for enabling features which require Octave version >= major.minor.patch +// - Use (OCTAVE_PATCH_VERSION + 0) to handle both '' (released) and '+' (in development) patch numbers +#define SWIG_OCTAVE_PREREQ(major, minor, patch) \ + ( (OCTAVE_MAJOR_VERSION<<16) + (OCTAVE_MINOR_VERSION<<8) + (OCTAVE_PATCH_VERSION + 0) >= ((major)<<16) + ((minor)<<8) + (patch) ) + +// Reconstruct Octave major, minor, and patch versions for releases prior to 3.8.1 +#if !defined(OCTAVE_MAJOR_VERSION) + +# if !defined(OCTAVE_API_VERSION_NUMBER) + +// Hack to distinguish between Octave 3.8.0, which removed OCTAVE_API_VERSION_NUMBER but did not yet +// introduce OCTAVE_MAJOR_VERSION, and Octave <= 3.2, which did not define OCTAVE_API_VERSION_NUMBER +# include +# if defined(octave_ov_h) +# define OCTAVE_MAJOR_VERSION 3 +# define OCTAVE_MINOR_VERSION 8 +# define OCTAVE_PATCH_VERSION 0 +# else + +// Hack to distinguish between Octave 3.2 and earlier versions, before OCTAVE_API_VERSION_NUMBER existed +# define ComplexLU __ignore +# include +# undef ComplexLU +# if defined(octave_Complex_LU_h) + +// We know only that this version is prior to Octave 3.2, i.e. OCTAVE_API_VERSION_NUMBER < 37 +# define OCTAVE_MAJOR_VERSION 3 +# define OCTAVE_MINOR_VERSION 1 +# define OCTAVE_PATCH_VERSION 99 + +# else + +// OCTAVE_API_VERSION_NUMBER == 37 +# define OCTAVE_MAJOR_VERSION 3 +# define OCTAVE_MINOR_VERSION 2 +# define OCTAVE_PATCH_VERSION 0 + +# endif // defined(octave_Complex_LU_h) + +# endif // defined(octave_ov_h) + +// Correlation between Octave API and version numbers extracted from Octave's +// ChangeLogs; version is the *earliest* released Octave with that API number +# elif OCTAVE_API_VERSION_NUMBER >= 48 +# define OCTAVE_MAJOR_VERSION 3 +# define OCTAVE_MINOR_VERSION 6 +# define OCTAVE_PATCH_VERSION 0 + +# elif OCTAVE_API_VERSION_NUMBER >= 45 +# define OCTAVE_MAJOR_VERSION 3 +# define OCTAVE_MINOR_VERSION 4 +# define OCTAVE_PATCH_VERSION 1 + +# elif OCTAVE_API_VERSION_NUMBER >= 42 +# define OCTAVE_MAJOR_VERSION 3 +# define OCTAVE_MINOR_VERSION 3 +# define OCTAVE_PATCH_VERSION 54 + +# elif OCTAVE_API_VERSION_NUMBER >= 41 +# define OCTAVE_MAJOR_VERSION 3 +# define OCTAVE_MINOR_VERSION 3 +# define OCTAVE_PATCH_VERSION 53 + +# elif OCTAVE_API_VERSION_NUMBER >= 40 +# define OCTAVE_MAJOR_VERSION 3 +# define OCTAVE_MINOR_VERSION 3 +# define OCTAVE_PATCH_VERSION 52 + +# elif OCTAVE_API_VERSION_NUMBER >= 39 +# define OCTAVE_MAJOR_VERSION 3 +# define OCTAVE_MINOR_VERSION 3 +# define OCTAVE_PATCH_VERSION 51 + +# else // OCTAVE_API_VERSION_NUMBER == 38 +# define OCTAVE_MAJOR_VERSION 3 +# define OCTAVE_MINOR_VERSION 3 +# define OCTAVE_PATCH_VERSION 50 + +# endif // !defined(OCTAVE_API_VERSION_NUMBER) + +#endif // !defined(OCTAVE_MAJOR_VERSION) + #include #include #include @@ -9,8 +95,16 @@ #include #include #include +#if SWIG_OCTAVE_PREREQ(4,2,0) +#include +#else #include +#endif #include +#if SWIG_OCTAVE_PREREQ(4,2,0) +#include +#endif + %} %insert(runtime) "swigrun.swg"; @@ -24,27 +118,38 @@ static bool SWIG_init_user(octave_swig_type* module_ns); SWIGINTERN bool SWIG_Octave_LoadModule(std::string name) { - bool retn; + bool retn = false; { -#if !SWIG_OCTAVE_PREREQ(3,3,50) - unwind_protect::begin_frame("SWIG_Octave_LoadModule"); - unwind_protect_int(error_state); - unwind_protect_int(warning_state); - unwind_protect_bool(discard_error_messages); - unwind_protect_bool(discard_warning_messages); -#else +#if SWIG_OCTAVE_PREREQ(4,2,0) + octave::unwind_protect frame; + frame.protect_var(discard_error_messages); discard_error_messages = true; + frame.protect_var(discard_warning_messages); discard_warning_messages = true; +#elif SWIG_OCTAVE_PREREQ(3,3,50) unwind_protect frame; - frame.protect_var(error_state); - frame.protect_var(warning_state); - frame.protect_var(discard_error_messages); - frame.protect_var(discard_warning_messages); + frame.protect_var(error_state); error_state = 0; + frame.protect_var(warning_state); warning_state = 0; + frame.protect_var(discard_error_messages); discard_error_messages = true; + frame.protect_var(discard_warning_messages); discard_warning_messages = true; +#else + unwind_protect::begin_frame("SWIG_Octave_LoadModule"); + unwind_protect_int(error_state); error_state = 0; + unwind_protect_int(warning_state); warning_state = 0; + unwind_protect_bool(discard_error_messages); discard_error_messages = true; + unwind_protect_bool(discard_warning_messages); discard_warning_messages = true; #endif - error_state = 0; - warning_state = 0; - discard_error_messages = true; - discard_warning_messages = true; +#if SWIG_OCTAVE_PREREQ(4,2,0) + try { +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::feval(name, octave_value_list(), 0); +#else + feval(name, octave_value_list(), 0); +#endif + retn = true; + } catch (octave::execution_exception&) { } +#else feval(name, octave_value_list(), 0); retn = (error_state == 0); +#endif #if !SWIG_OCTAVE_PREREQ(3,3,50) unwind_protect::run_frame("SWIG_Octave_LoadModule"); #endif @@ -56,31 +161,41 @@ SWIGINTERN bool SWIG_Octave_LoadModule(std::string name) { } SWIGINTERN bool SWIG_Octave_InstallFunction(octave_function *octloadfcn, std::string name) { - bool retn; + bool retn = false; { -#if !SWIG_OCTAVE_PREREQ(3,3,50) - unwind_protect::begin_frame("SWIG_Octave_InstallFunction"); - unwind_protect_int(error_state); - unwind_protect_int(warning_state); - unwind_protect_bool(discard_error_messages); - unwind_protect_bool(discard_warning_messages); -#else +#if SWIG_OCTAVE_PREREQ(4,2,0) + octave::unwind_protect frame; + frame.protect_var(discard_error_messages); discard_error_messages = true; + frame.protect_var(discard_warning_messages); discard_warning_messages = true; +#elif SWIG_OCTAVE_PREREQ(3,3,50) unwind_protect frame; - frame.protect_var(error_state); - frame.protect_var(warning_state); - frame.protect_var(discard_error_messages); - frame.protect_var(discard_warning_messages); + frame.protect_var(error_state); error_state = 0; + frame.protect_var(warning_state); warning_state = 0; + frame.protect_var(discard_error_messages); discard_error_messages = true; + frame.protect_var(discard_warning_messages); discard_warning_messages = true; +#else + unwind_protect::begin_frame("SWIG_Octave_InstallFunction"); + unwind_protect_int(error_state); error_state = 0; + unwind_protect_int(warning_state); warning_state = 0; + unwind_protect_bool(discard_error_messages); discard_error_messages = true; + unwind_protect_bool(discard_warning_messages); discard_warning_messages = true; #endif - error_state = 0; - warning_state = 0; - discard_error_messages = true; - discard_warning_messages = true; octave_value_list args; args.append(name); args.append(octloadfcn->fcn_file_name()); - error_state = 0; +#if SWIG_OCTAVE_PREREQ(4,2,0) + try { +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::feval("autoload", args, 0); +#else + feval("autoload", args, 0); +#endif + retn = true; + } catch (octave::execution_exception&) { } +#else feval("autoload", args, 0); retn = (error_state == 0); +#endif #if !SWIG_OCTAVE_PREREQ(3,3,50) unwind_protect::run_frame("SWIG_Octave_InstallFunction"); #endif @@ -205,16 +320,21 @@ static const char *const SWIG_name_usage = "-*- texinfo -*- \n\ Loads the SWIG-generated module `" SWIG_name_d "'.\n\ @end deftypefn"; +void __swig_atexit__(void) { ::_Exit(0); } + DEFUN_DLD( SWIG_name, args, nargout, SWIG_name_usage ) { static octave_swig_type* module_ns = 0; // workaround to prevent octave seg-faulting on exit: set Octave exit function // octave_exit to _Exit, which exits 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 off with macro definition. + // definitely affected version 3.2.*, not sure about 3.3.*, seems to be fixed in + // version 3.4.*, but reappeared in 4.2.*, so turn on for all versions after 3.2.*. + // can be turned off with macro definition. #ifndef SWIG_OCTAVE_NO_SEGFAULT_HACK -#if SWIG_OCTAVE_PREREQ(3,2,0) && !SWIG_OCTAVE_PREREQ(3,4,1) +#if SWIG_OCTAVE_PREREQ(4,4,0) + atexit(__swig_atexit__); +#elif SWIG_OCTAVE_PREREQ(3,2,0) octave_exit = ::_Exit; #endif #endif @@ -243,15 +363,54 @@ DEFUN_DLD( SWIG_name, args, nargout, SWIG_name_usage ) { "__swig_atexit__; " "atexit(\"__swig_atexit__\", false); " "atexit(\"__swig_atexit__\")"); +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::feval("evalin", eval_args, 0); +#else feval("evalin", eval_args, 0); #endif +#endif +#if SWIG_OCTAVE_PREREQ(4,4,0) + { + octave::type_info& typeinfo = octave::interpreter::the_interpreter()->get_type_info(); + string_vector types = typeinfo.installed_type_names(); + bool register_octave_swig_ref = true; + bool register_octave_swig_packed = true; + bool register_octave_swig_bound_func = true; + for (int i = 0; i < types.numel(); ++i) { + if (types(i) == octave_swig_ref::static_type_name()) { + register_octave_swig_ref = false; + } + if (types(i) == octave_swig_packed::static_type_name()) { + register_octave_swig_packed = false; + } + if (types(i) == octave_swig_bound_func::static_type_name()) { + register_octave_swig_bound_func = false; + } + } + if (register_octave_swig_ref) { + octave_swig_ref::register_type(); + } + if (register_octave_swig_packed) { + octave_swig_packed::register_type(); + } + if (register_octave_swig_bound_func) { + octave_swig_bound_func::register_type(); + } + } +#else octave_swig_ref::register_type(); octave_swig_packed::register_type(); +#endif SWIG_InitializeModule(0); SWIG_PropagateClientData(); +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::call_stack& stack = octave::interpreter::the_interpreter()->get_call_stack(); + octave_function *me = stack.current(); +#else octave_function *me = octave_call_stack::current(); +#endif if (!SWIG_Octave_InstallFunction(me, "subclass")) { return octave_value_list(); @@ -318,10 +477,12 @@ DEFUN_DLD( SWIG_name, args, nargout, SWIG_name_usage ) { } } -#if !SWIG_OCTAVE_PREREQ(3,2,0) - mlock(me->name()); -#else +#if SWIG_OCTAVE_PREREQ(4,4,0) + octave::interpreter::the_interpreter()->mlock(); +#elif SWIG_OCTAVE_PREREQ(3,2,0) mlock(); +#else + mlock(me->name()); #endif } diff --git a/Lib/octave/octstdcommon.swg b/Lib/octave/octstdcommon.swg index 799d369a7..80b2154d9 100644 --- a/Lib/octave/octstdcommon.swg +++ b/Lib/octave/octstdcommon.swg @@ -41,7 +41,7 @@ namespace swig { template struct traits_asptr { static int asptr(const octave_value& obj, Type **val) { - Type *p; + Type *p = 0; swig_type_info *descriptor = type_info(); int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; if (SWIG_IsOK(res)) { @@ -103,14 +103,14 @@ namespace swig { template struct traits_as { - static Type as(const octave_value& obj, bool throw_error) { + static Type as(const octave_value& obj) { Type v; int res = asval(obj, &v); if (!obj.is_defined() || !SWIG_IsOK(res)) { if (!Octave_Error_Occurred()) { %type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); + throw std::invalid_argument("bad type"); } return v; } @@ -118,7 +118,7 @@ namespace swig { template struct traits_as { - static Type as(const octave_value& obj, bool throw_error) { + static Type as(const octave_value& obj) { Type *v = 0; int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res) && v) { @@ -130,21 +130,17 @@ namespace swig { return *v; } } else { - // Uninitialized return value, no Type() constructor required. - static Type *v_def = (Type*) malloc(sizeof(Type)); if (!Octave_Error_Occurred()) { %type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); - memset(v_def,0,sizeof(Type)); - return *v_def; + throw std::invalid_argument("bad type"); } } }; template struct traits_as { - static Type* as(const octave_value& obj, bool throw_error) { + static Type* as(const octave_value& obj) { Type *v = 0; int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res)) { @@ -153,15 +149,14 @@ namespace swig { if (!Octave_Error_Occurred()) { %type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); - return 0; + throw std::invalid_argument("bad type"); } } }; template - inline Type as(const octave_value& obj, bool te = false) { - return traits_as::category>::as(obj, te); + inline Type as(const octave_value& obj) { + return traits_as::category>::as(obj); } template diff --git a/Lib/octave/std_basic_string.i b/Lib/octave/std_basic_string.i index 19712e8d0..01a2c34a2 100644 --- a/Lib/octave/std_basic_string.i +++ b/Lib/octave/std_basic_string.i @@ -10,24 +10,20 @@ %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsCharPtrAndSize") { SWIGINTERN int -SWIG_AsPtr(std::basic_string)(octave_value obj, std::string **val) -{ +SWIG_AsPtr(std::basic_string)(octave_value obj, std::string **val) { if (obj.is_string()) { if (val) *val = new std::string(obj.string_value()); return SWIG_NEWOBJ; } - if (val) - error("a string is expected"); - return 0; + return SWIG_ERROR; } } %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromCharPtrAndSize") { SWIGINTERNINLINE octave_value - SWIG_From(std::basic_string)(const std::string& s) - { + SWIG_From(std::basic_string)(const std::string& s) { return SWIG_FromCharPtrAndSize(s.data(), s.size()); } } @@ -45,41 +41,20 @@ SWIGINTERNINLINE octave_value %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsWCharPtrAndSize") { SWIGINTERN int - SWIG_AsPtr(std::basic_string)(PyObject* obj, std::wstring **val) - { - static swig_type_info* string_info = - SWIG_TypeQuery("std::basic_string *"); - std::wstring *vptr; - if (SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0) == SWIG_OK) { - if (val) *val = vptr; - return SWIG_OLDOBJ; - } else { - PyErr_Clear(); - wchar_t *buf = 0 ; size_t size = 0; int alloc = 0; - if (SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc) == SWIG_OK) { - if (buf) { - if (val) *val = new std::wstring(buf, size - 1); - if (alloc == SWIG_NEWOBJ) %delete_array(buf); - return SWIG_NEWOBJ; - } - } else { - PyErr_Clear(); - } - if (val) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(PyExc_TypeError,"a wstring is expected"); - SWIG_PYTHON_THREAD_END_BLOCK; - } - return 0; - } +SWIG_AsPtr(std::basic_string)(octave_value obj, std::wstring **val) { + if (obj.is_string()) { + if (val) + *val = new std::wstring(obj.string_value()); + return SWIG_NEWOBJ; } + return SWIG_ERROR; +} } %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromWCharPtrAndSize") { SWIGINTERNINLINE PyObject* - SWIG_From(std::basic_string)(const std::wstring& s) - { + SWIG_From(std::basic_string)(const std::wstring& s) { return SWIG_FromWCharPtrAndSize(s.data(), s.size()); } } diff --git a/Lib/octave/std_complex.i b/Lib/octave/std_complex.i index 771728b9d..30c188244 100644 --- a/Lib/octave/std_complex.i +++ b/Lib/octave/std_complex.i @@ -8,6 +8,13 @@ #include %} +namespace std { + %naturalvar complex; + template class complex; + %template() complex; + %template() complex; +} + /* defining the complex as/from converters */ %swig_cplxdbl_convn(std::complex, std::complex, std::real, std::imag) diff --git a/Lib/octave/std_deque.i b/Lib/octave/std_deque.i index 6866a610f..c40cfee12 100644 --- a/Lib/octave/std_deque.i +++ b/Lib/octave/std_deque.i @@ -12,7 +12,7 @@ template struct traits_from > { - static octave_value from(const std::deque & vec) { + static octave_value from(const std::deque& vec) { return traits_from_stdseq >::from(vec); } }; diff --git a/Lib/octave/std_list.i b/Lib/octave/std_list.i index 1421efaee..35f6c1321 100644 --- a/Lib/octave/std_list.i +++ b/Lib/octave/std_list.i @@ -12,7 +12,7 @@ template struct traits_from > { - static octave_value *from(const std::list & vec) { + static octave_value *from(const std::list& vec) { return traits_from_stdseq >::from(vec); } }; diff --git a/Lib/octave/std_pair.i b/Lib/octave/std_pair.i index a06498bf2..2f307380e 100644 --- a/Lib/octave/std_pair.i +++ b/Lib/octave/std_pair.i @@ -38,7 +38,13 @@ } static int asval(const octave_value& obj, std::pair *val) { - if (obj.is_cell()) { + if ( +%#if SWIG_OCTAVE_PREREQ(4,4,0) + obj.iscell() +%#else + obj.is_cell() +%#endif + ) { Cell c=obj.cell_value(); if (c.numel()<2) { error("pair from Cell array requires at least two elements"); @@ -69,12 +75,16 @@ value_type *vp = %new_instance(std::pair); T *pfirst = &(vp->first); int res1 = swig::asval(first, pfirst); - if (!SWIG_IsOK(res1)) + if (!SWIG_IsOK(res1)) { + %delete(vp); return res1; + } U *psecond = &(vp->second); int res2 = swig::asval(second, psecond); - if (!SWIG_IsOK(res2)) + if (!SWIG_IsOK(res2)) { + %delete(vp); return res2; + } *val = vp; return SWIG_AddNewMask(res1 > res2 ? res1 : res2); } else { @@ -92,7 +102,13 @@ } static int asptr(const octave_value& obj, std::pair **val) { - if (obj.is_cell()) { + if ( +%#if SWIG_OCTAVE_PREREQ(4,4,0) + obj.iscell() +%#else + obj.is_cell() +%#endif + ) { Cell c=obj.cell_value(); if (c.numel()<2) { error("pair from Cell array requires at least two elements"); diff --git a/Lib/octave/std_wstring.i b/Lib/octave/std_wstring.i new file mode 100644 index 000000000..dc1378ae6 --- /dev/null +++ b/Lib/octave/std_wstring.i @@ -0,0 +1 @@ +%include diff --git a/Lib/octave/stl.i b/Lib/octave/stl.i index b29f7d84d..04f86014f 100644 --- a/Lib/octave/stl.i +++ b/Lib/octave/stl.i @@ -1,6 +1,10 @@ -/* initial STL definition. extended as needed in each language */ +/* ----------------------------------------------------------------------------- + * stl.i + * ----------------------------------------------------------------------------- */ + %include %include %include %include %include + diff --git a/Lib/perl5/cni.i b/Lib/perl5/cni.i deleted file mode 100644 index c4d4eafa8..000000000 --- a/Lib/perl5/cni.i +++ /dev/null @@ -1,12 +0,0 @@ -%warnfilter(SWIGWARN_PARSE_KEYWORD) java::lang::ref; - -%{ -#undef STATIC -%} -%include -%{ -#undef TRUE -#define TRUE 1 -%} - -%include diff --git a/Lib/perl5/jstring.i b/Lib/perl5/jstring.i deleted file mode 100644 index 1c179b754..000000000 --- a/Lib/perl5/jstring.i +++ /dev/null @@ -1,48 +0,0 @@ -%include - -%fragment(SWIG_AsVal_frag(jstring),"header") { -SWIGINTERN int -SWIG_AsVal_dec(jstring)(SV *obj, jstring *val) -{ - if (SvPOK(obj)) { - if (val) { - STRLEN len = 0; - char *cstr = SvPV(obj, len); - *val = JvNewStringLatin1(cstr, len); - } - return SWIG_OK; - } - return SWIG_ERROR; -} -} - -%fragment(SWIG_From_frag(jstring),"header") { -SWIGINTERNINLINE SV * -SWIG_From_dec(jstring)(jstring val) -{ - SV *obj = sv_newmortal(); - if (!val) { - sv_setsv(obj, &PL_sv_undef); - } else { - jsize len = JvGetStringUTFLength(val); - if (!len) { - sv_setsv(obj, &PL_sv_undef); - } else { - char *tmp = %new_array(len, char); - JvGetStringUTFRegion(val, 0, len, tmp); - sv_setpvn(obj, tmp, len); - SvUTF8_on(obj); - %delete_array(tmp); - } - } - return obj; -} -} - -%typemaps_asvalfrom(%checkcode(STRING), - %arg(SWIG_AsVal(jstring)), - %arg(SWIG_From(jstring)), - %arg(SWIG_AsVal_frag(jstring)), - %arg(SWIG_From_frag(jstring)), - java::lang::String *); - diff --git a/Lib/perl5/perlrun.swg b/Lib/perl5/perlrun.swg index d1865de0a..b04002f5d 100644 --- a/Lib/perl5/perlrun.swg +++ b/Lib/perl5/perlrun.swg @@ -20,6 +20,7 @@ #define SWIG_ConvertPtr(obj, pp, type, flags) SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags) #define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own) #define SWIG_NewPointerObj(p, type, flags) SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags) +#define SWIG_AcquirePtr(ptr, src) SWIG_Perl_AcquirePtr(ptr, src) #define swig_owntype int /* for raw packed data */ @@ -229,6 +230,14 @@ SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) { return 0; } +/* Acquire a pointer value */ + +SWIGRUNTIME int +SWIG_Perl_AcquirePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, int own) { + /* TODO */ + return 0; +} + /* Function for getting a pointer value */ SWIGRUNTIME int @@ -268,7 +277,7 @@ SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_ voidptr = INT2PTR(void *,tmp); } else if (! SvOK(sv)) { /* Check for undef */ *(ptr) = (void *) 0; - return SWIG_OK; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } else if (SvTYPE(sv) == SVt_RV) { /* Check for NULL pointer */ if (!SvROK(sv)) { /* In Perl 5.12 and later, SVt_RV == SVt_IV, so sv could be a valid integer value. */ @@ -392,7 +401,7 @@ SWIG_Perl_NewPackedObj(SWIG_MAYBE_PERL_OBJECT void *ptr, int sz, swig_type_info return result; } -/* Convert a packed value value */ +/* Convert a packed pointer value */ SWIGRUNTIME int SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) { swig_cast_info *tc; diff --git a/Lib/perl5/perltypemaps.swg b/Lib/perl5/perltypemaps.swg index ffec5eaf1..bf1596e9f 100644 --- a/Lib/perl5/perltypemaps.swg +++ b/Lib/perl5/perltypemaps.swg @@ -43,7 +43,7 @@ /* Perl types */ #define SWIG_Object SV * -#define VOID_Object sv_newmortal() +#define VOID_Object &PL_sv_undef /* Perl $shadow flag */ #define %newpointer_flags $shadow @@ -56,7 +56,7 @@ %define %set_output(obj) $result = obj; argvi++ %enddef /* append output */ -%define %append_output(obj) if (argvi >= items) EXTEND(sp,1); %set_output(obj) %enddef +%define %append_output(obj) if (argvi >= items) EXTEND(sp, argvi+1); %set_output(obj) %enddef /* variable output */ %define %set_varoutput(obj) sv_setsv($result,obj) %enddef @@ -71,6 +71,10 @@ /* raise exception */ %define %raise(obj, type, desc) sv_setsv(get_sv("@", GV_ADD), obj); SWIG_fail %enddef +/* For directors to raise/throw the original exception */ +%typemap(throws) Swig::DirectorException +%{ sv_setsv(ERRSV, $1.getNative()); SWIG_fail; %} + /* Include the unified typemap library */ %include diff --git a/Lib/perl5/std_common.i b/Lib/perl5/std_common.i index bb280688e..7c1ff2328 100644 --- a/Lib/perl5/std_common.i +++ b/Lib/perl5/std_common.i @@ -10,14 +10,17 @@ %fragment(""); %{ +SWIGINTERN double SwigSvToNumber(SV* sv) { return SvIOK(sv) ? double(SvIVX(sv)) : SvNVX(sv); } +SWIGINTERN std::string SwigSvToString(SV* sv) { STRLEN len; char *ptr = SvPV(sv, len); return std::string(ptr, len); } +SWIGINTERN void SwigSvFromString(SV* sv, const std::string& s) { sv_setpvn(sv,s.data(),s.size()); } diff --git a/Lib/perl5/std_list.i b/Lib/perl5/std_list.i index cd5a61120..36678add2 100644 --- a/Lib/perl5/std_list.i +++ b/Lib/perl5/std_list.i @@ -189,11 +189,15 @@ namespace std { } public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef const value_type& const_reference; list(); - list(const list &); + list(const list& other); unsigned int size() const; bool empty() const; @@ -346,7 +350,7 @@ namespace std { typedef const value_type& const_reference; list(); - list(const list &); + list(const list& other); unsigned int size() const; bool empty() const; diff --git a/Lib/perl5/std_map.i b/Lib/perl5/std_map.i index af49ed38e..1b3731832 100644 --- a/Lib/perl5/std_map.i +++ b/Lib/perl5/std_map.i @@ -20,22 +20,28 @@ namespace std { - template class map { + template > class map { // add typemaps here public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { const T& get(const K& key) throw (std::out_of_range) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -45,14 +51,14 @@ namespace std { (*self)[key] = x; } void del(const K& key) throw (std::out_of_range) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map< K, T >::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } } diff --git a/Lib/perl5/std_pair.i b/Lib/perl5/std_pair.i index 0712ad762..732347db5 100644 --- a/Lib/perl5/std_pair.i +++ b/Lib/perl5/std_pair.i @@ -18,12 +18,14 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; pair(); - pair(T t, U u); - pair(const pair& p); + pair(T first, U second); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/perl5/std_vector.i b/Lib/perl5/std_vector.i index ec8449464..5bfd2c5ac 100644 --- a/Lib/perl5/std_vector.i +++ b/Lib/perl5/std_vector.i @@ -181,11 +181,16 @@ namespace std { } public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef const value_type& const_reference; + vector(unsigned int size = 0); vector(unsigned int size, const T& value); - vector(const vector &); + vector(const vector& other); unsigned int size() const; bool empty() const; @@ -353,11 +358,16 @@ namespace std { } public: typedef size_t size_type; - typedef T value_type; + typedef ptrdiff_t difference_type; + typedef T* value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef const value_type& const_reference; + vector(unsigned int size = 0); vector(unsigned int size, T *value); - vector(const vector &); + vector(const vector& other); unsigned int size() const; bool empty() const; @@ -524,11 +534,16 @@ namespace std { } public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef const value_type& const_reference; + vector(unsigned int size = 0); vector(unsigned int size, T value); - vector(const vector &); + vector(const vector& other); unsigned int size() const; bool empty() const; diff --git a/Lib/perl5/stl.i b/Lib/perl5/stl.i index b19eae58b..04f86014f 100644 --- a/Lib/perl5/stl.i +++ b/Lib/perl5/stl.i @@ -1,8 +1,7 @@ /* ----------------------------------------------------------------------------- * stl.i - * - * Initial STL definition. extended as needed in each language * ----------------------------------------------------------------------------- */ + %include %include %include diff --git a/Lib/perl5/typemaps.i b/Lib/perl5/typemaps.i index 7d96f2ace..3e1f60d90 100644 --- a/Lib/perl5/typemaps.i +++ b/Lib/perl5/typemaps.i @@ -168,7 +168,7 @@ output values. bool *OUTPUT, bool &OUTPUT { if (argvi >= items) { - EXTEND(sp,1); + EXTEND(sp, argvi+1); } $result = sv_newmortal(); sv_setiv($result,(IV) *($1)); @@ -181,7 +181,7 @@ output values. unsigned char *OUTPUT, unsigned char &OUTPUT { if (argvi >= items) { - EXTEND(sp,1); + EXTEND(sp, argvi+1); } $result = sv_newmortal(); sv_setuv($result,(UV) *($1)); @@ -194,7 +194,7 @@ output values. double *OUTPUT, double &OUTPUT { if (argvi >= items) { - EXTEND(sp,1); + EXTEND(sp, argvi+1); } $result = sv_newmortal(); sv_setnv($result,(double) *($1)); @@ -204,7 +204,7 @@ output values. %typemap(argout) long long *OUTPUT, long long &OUTPUT { char temp[256]; if (argvi >= items) { - EXTEND(sp,1); + EXTEND(sp, argvi+1); } sprintf(temp,"%lld", (long long)*($1)); $result = sv_newmortal(); @@ -215,7 +215,7 @@ output values. %typemap(argout) unsigned long long *OUTPUT, unsigned long long &OUTPUT { char temp[256]; if (argvi >= items) { - EXTEND(sp,1); + EXTEND(sp, argvi+1); } sprintf(temp,"%llu", (unsigned long long)*($1)); $result = sv_newmortal(); diff --git a/Lib/php/const.i b/Lib/php/const.i index 061ba99a2..32b4b9b0b 100644 --- a/Lib/php/const.i +++ b/Lib/php/const.i @@ -12,10 +12,12 @@ unsigned long, unsigned char, signed char, - bool, enum SWIGTYPE "SWIG_LONG_CONSTANT($symname, ($1_type)$value);"; +%typemap(consttab) bool + "SWIG_BOOL_CONSTANT($symname, ($1_type)$value);"; + %typemap(consttab) float, double "SWIG_DOUBLE_CONSTANT($symname, $value);"; @@ -33,18 +35,12 @@ SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] { - zval *z_var; zend_constant c; - size_t len = sizeof("$symname") - 1; - MAKE_STD_ZVAL(z_var); - SWIG_SetPointerZval(z_var, (void*)$value, $1_descriptor, 0); - c.value = *z_var; + SWIG_SetPointerZval(&c.value, (void*)$value, $1_descriptor, 0); zval_copy_ctor(&c.value); - c.name = zend_strndup("$symname", len); - c.name_len = len+1; - c.flags = CONST_CS | CONST_PERSISTENT; - c.module_number = module_number; - zend_register_constant( &c TSRMLS_CC ); + c.name = zend_string_init("$symname", sizeof("$symname") - 1, 0); + SWIG_ZEND_CONSTANT_SET_FLAGS(&c, CONST_CS, module_number); + zend_register_constant(&c); } /* Handled as a global variable. */ diff --git a/Lib/php/director.swg b/Lib/php/director.swg index 638a1697d..ea0eba8ac 100644 --- a/Lib/php/director.swg +++ b/Lib/php/director.swg @@ -77,30 +77,30 @@ namespace Swig { class Director { protected: - zval *swig_self; + // "mutable" so we can get a non-const pointer to it in const methods. + mutable zval swig_self; typedef std::map swig_ownership_map; mutable swig_ownership_map swig_owner; -#ifdef ZTS - // Store the ZTS context so it's available when C++ calls back to PHP. - void *** swig_zts_ctx; -#endif public: - Director(zval *self TSRMLS_DC) : swig_self(self) { - TSRMLS_SET_CTX(swig_zts_ctx); + Director(zval *self) { + ZVAL_COPY_VALUE(&swig_self, self); } - static bool swig_is_overridden_method(char *cname, char *lc_fname TSRMLS_DC) { - zend_class_entry **ce; - zend_function *mptr; - - if (zend_lookup_class(cname, strlen(cname), &ce TSRMLS_CC) != SUCCESS) { - return false; + static bool swig_is_overridden_method(const char *cname, const char *lc_fname) { + bool result = false; + zend_string * cname_str = zend_string_init(cname, strlen(cname), 0); + zend_class_entry *ce = zend_lookup_class(cname_str); + if (ce) { + zval * mptr = zend_hash_str_find(&ce->function_table, lc_fname, strlen(lc_fname)); + if (mptr) { + // common.scope points to zend_class_entry for the declaring class, + // and there's only one of those per class, so we can just use a + // pointer compare here. + result = Z_FUNC_P(mptr)->common.scope != ce; + } } - if (zend_hash_find(&(*ce)->function_table, lc_fname, strlen(lc_fname) + 1, (void **) &mptr) != SUCCESS) { - return false; - } - // common.scope points to the declaring class - return strcmp(mptr->common.scope->name, cname); + zend_string_release(cname_str); + return result; } template @@ -116,8 +116,8 @@ namespace Swig { protected: std::string swig_msg; public: - DirectorException(int code, const char *hdr, const char *msg TSRMLS_DC) : swig_msg(hdr) { - if (msg[0]) { + DirectorException(int code, const char *hdr, const char *msg) : swig_msg(hdr) { + if (msg && msg[0]) { swig_msg += " "; swig_msg += msg; } @@ -132,20 +132,20 @@ namespace Swig { return swig_msg.c_str(); } - static void raise(int code, const char *hdr, const char *msg TSRMLS_DC) { - throw DirectorException(code, hdr, msg TSRMLS_CC); + static void raise(int code, const char *hdr, const char *msg) { + throw DirectorException(code, hdr, msg); } }; /* attempt to call a pure virtual method via a director method */ class DirectorPureVirtualException : public DirectorException { public: - DirectorPureVirtualException(const char *msg TSRMLS_DC) - : DirectorException(E_ERROR, "SWIG director pure virtual method called", msg TSRMLS_CC) { + DirectorPureVirtualException(const char *msg) + : DirectorException(E_ERROR, "SWIG director pure virtual method called", msg) { } - static void raise(const char *msg TSRMLS_DC) { - throw DirectorPureVirtualException(msg TSRMLS_CC); + static void raise(const char *msg) { + throw DirectorPureVirtualException(msg); } }; @@ -153,18 +153,18 @@ namespace Swig { class DirectorMethodException : public DirectorException { public: - DirectorMethodException(const char *msg TSRMLS_DC) - : DirectorException(E_ERROR, "SWIG director method error", msg TSRMLS_CC) { + DirectorMethodException() + : DirectorException(E_ERROR, "SWIG director method error", NULL) { } - static void raise(const char *msg TSRMLS_DC) { - throw DirectorMethodException(msg TSRMLS_CC); + DirectorMethodException(const char *msg) + : DirectorException(E_ERROR, "SWIG director method error", msg) { + } + + static void raise(const char *msg) { + throw DirectorMethodException(msg); } }; } -// DirectorMethodException() is documented to be callable with no parameters -// so use a macro to insert TSRMLS_CC so any ZTS context gets passed. -#define DirectorMethodException() DirectorMethodException("" TSRMLS_CC) - #endif diff --git a/Lib/php/globalvar.i b/Lib/php/globalvar.i index 4f21c5cbf..6b31207a6 100644 --- a/Lib/php/globalvar.i +++ b/Lib/php/globalvar.i @@ -4,20 +4,22 @@ * Global variables - add the variable to PHP * ----------------------------------------------------------------------------- */ -%typemap(varinit) char *, - char [] +%typemap(varinit) char * { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_STRING; - if($1) { - z_var->value.str.val = estrdup($1); - z_var->value.str.len = strlen($1); + zval z_var; + if ($1) { + ZVAL_STRING(&z_var, $1); } else { - z_var->value.str.val = 0; - z_var->value.str.len = 0; + ZVAL_STR(&z_var, ZSTR_EMPTY_ALLOC()); } - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); +} + +%typemap(varinit) char [] +{ + zval z_var; + ZVAL_STRING(&z_var, $1); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) int, @@ -31,139 +33,98 @@ unsigned char, enum SWIGTYPE { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_LONG; - z_var->value.lval = (long)$1; - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); + zval z_var; + ZVAL_LONG(&z_var, (long)$1); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) bool { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_BOOL; - z_var->value.lval = ($1)?1:0; - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); + zval z_var; + ZVAL_BOOL(&z_var, ($1)?1:0); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) float, double { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_DOUBLE; - z_var->value.dval = $1; - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, - sizeof(zval *), NULL); + zval z_var; + ZVAL_DOUBLE(&z_var, (double)$1); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) char { - zval *z_var; - char c[2]; - MAKE_STD_ZVAL(z_var); - c[0] = $1; - c[1] = 0; - z_var->type = IS_STRING; - z_var->value.str.val = estrndup(c, 1); - z_var->value.str.len = 1; - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, - sizeof(zval *), NULL); + zval z_var; + char c = $1; + ZVAL_STRINGL(&z_var, &c, 1); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) SWIGTYPE *, SWIGTYPE [] { - zval *z_var; - MAKE_STD_ZVAL(z_var); - SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, 0); - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, - sizeof(zval *), NULL); + zval z_var; + SWIG_SetPointerZval(&z_var, (void*)$1, $1_descriptor, 0); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) SWIGTYPE, SWIGTYPE &, SWIGTYPE && { - zval *z_var; - - MAKE_STD_ZVAL(z_var); - SWIG_SetPointerZval(z_var, (void*)&$1, $&1_descriptor, 0); - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&z_var, - sizeof(zval *), NULL); + zval z_var; + SWIG_SetPointerZval(&z_var, (void*)&$1, $&1_descriptor, 0); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) char [ANY] { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_STRING; - if ($1) { - /* varinit char [ANY] */ - ZVAL_STRINGL(z_var,(char*)$1, $1_dim0, 1); - } - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&z_var, sizeof(zval *), NULL); + zval z_var; + /* varinit char [ANY] */ + ZVAL_STRINGL(&z_var, $1, $1_dim0); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) { + zval resource; void * p = emalloc(sizeof($1)); memcpy(p, &$1, sizeof($1)); - zval * resource; - MAKE_STD_ZVAL(resource); - ZEND_REGISTER_RESOURCE(resource, p, swig_member_ptr); - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&resource, sizeof(zval *), NULL); + ZVAL_RES(&resource, zend_register_resource(p, swig_member_ptr)); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &resource); } %typemap(varin) int, unsigned int, short, unsigned short, long, unsigned long, signed char, unsigned char, enum SWIGTYPE { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - convert_to_long_ex(z_var); - if ($1 != ($1_ltype)((*z_var)->value.lval)) { - $1 = Z_LVAL_PP(z_var); - } + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + $1 = zval_get_long(z_var); } %typemap(varin) bool { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - convert_to_boolean_ex(z_var); - if ($1 != ($1_ltype)((*z_var)->value.lval)) { - $1 = Z_LVAL_PP(z_var); - } + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + convert_to_boolean(z_var); + $1 = (Z_TYPE_P(z_var) == IS_TRUE); } %typemap(varin) double,float { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - convert_to_double_ex(z_var); - if ($1 != ($1_ltype)((*z_var)->value.dval)) { - $1 = Z_DVAL_PP(z_var); - } + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + $1 = zval_get_double(z_var); } %typemap(varin) char { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - convert_to_string_ex(z_var); - if ($1 != *((*z_var)->value.str.val)) { - $1 = *((*z_var)->value.str.val); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + convert_to_string(z_var); + if ($1 != Z_STRVAL_P(z_var)[0]) { + $1 = Z_STRVAL_P(z_var)[0]; } } %typemap(varin) char * { - zval **z_var; + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); char *s1; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - convert_to_string_ex(z_var); - s1 = Z_STRVAL_PP(z_var); + convert_to_string(z_var); + s1 = Z_STRVAL_P(z_var); if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { if (s1) $1 = estrdup(s1); @@ -175,48 +136,45 @@ %typemap(varin) SWIGTYPE [] { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1) { - SWIG_SetPointerZval(*z_var, (void*)$1, $1_descriptor, $owner); + if ($1) { + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, $owner); } } %typemap(varin) char [ANY] { - zval **z_var; - char *s1; + zval **z_var; + char *s1; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - s1 = Z_STRVAL_PP(z_var); - if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { - if (s1) - strncpy($1, s1, $1_dim0); - } + zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1, (void**)&z_var); + s1 = Z_STRVAL_P(z_var); + if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { + if (s1) + strncpy($1, s1, $1_dim0); + } } %typemap(varin) SWIGTYPE { - zval **z_var; + zval *z_var; $&1_ltype _temp; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if (SWIG_ConvertPtr(*z_var, (void**)&_temp, $&1_descriptor, 0) < 0) { + z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + if (SWIG_ConvertPtr(z_var, (void**)&_temp, $&1_descriptor, 0) < 0) { SWIG_PHP_Error(E_ERROR,"Type error in value of $symname. Expected $&1_descriptor"); } $1 = *($&1_ltype)_temp; - } %typemap(varin) SWIGTYPE *, SWIGTYPE &, SWIGTYPE && { - zval **z_var; + zval *z_var; $1_ltype _temp; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if (SWIG_ConvertPtr(*z_var, (void **)&_temp, $1_descriptor, 0) < 0) { + z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + if (SWIG_ConvertPtr(z_var, (void **)&_temp, $1_descriptor, 0) < 0) { SWIG_PHP_Error(E_ERROR,"Type error in value of $symname. Expected $&1_descriptor"); } @@ -225,10 +183,8 @@ %typemap(varin, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - void * p = (void*)zend_fetch_resource(*z_var TSRMLS_CC, -1, SWIG_MEMBER_PTR, NULL, 1, swig_member_ptr); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + void * p = (void*)zend_fetch_resource_ex(z_var, SWIG_MEMBER_PTR, swig_member_ptr); memcpy(&$1, p, sizeof($1)); } @@ -242,114 +198,96 @@ unsigned char, enum SWIGTYPE { - zval **z_var; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1 != ($1_ltype)((*z_var)->value.lval)) { - (*z_var)->value.lval = (long)$1; + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + if ($1 != ($1_ltype)Z_LVAL_P(z_var)) { + z_var->value.lval = (long)$1; } } //SAMFIX need to cast zval->type, what if zend-hash_find fails? etc? %typemap(varout) bool { - zval **z_var; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1 != ($1_ltype)((*z_var)->value.lval)) { - (*z_var)->value.lval = (long)$1; + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + if ($1 != ($1_ltype)Z_LVAL_P(z_var)) { + z_var->value.lval = (long)$1; } } %typemap(varout) double, float { - zval **z_var; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1 != ($1_ltype)((*z_var)->value.dval)) { - (*z_var)->value.dval = (double)$1; + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + if ($1 != ($1_ltype)Z_DVAL_P(z_var)) { + z_var->value.dval = (double)$1; } } %typemap(varout) char { - zval **z_var; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1 != *((*z_var)->value.str.val)) { - char c[2]; - efree((*z_var)->value.str.val); - c[0] = $1; - c[1] = 0; - (*z_var)->value.str.val = estrdup(c); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + char c = $1; + if ($1 != Z_STRVAL_P(z_val)[0]) { + ZVAL_STRING(z_var, &c); } } %typemap(varout) char * { - zval **z_var; - char *s1; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - s1 = Z_STRVAL_PP(z_var); - if((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { - if(s1) + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + const char *s1 = Z_STRVAL_P(z_var); + if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { + if (s1) efree(s1); - if($1) { - (*z_var)->value.str.val = estrdup($1); - (*z_var)->value.str.len = strlen($1) + 1; + if ($1) { + (z_var)->value.str.val = estrdup($1); + (z_var)->value.str.len = strlen($1) + 1; } else { - (*z_var)->value.str.val = 0; - (*z_var)->value.str.len = 0; + (z_var)->value.str.val = 0; + (z_var)->value.str.len = 0; } - } + } } %typemap(varout) SWIGTYPE { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - SWIG_SetPointerZval(*z_var, (void*)&$1, $&1_descriptor, 0); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + SWIG_SetPointerZval(z_var, (void*)&$1, $&1_descriptor, 0); } %typemap(varout) SWIGTYPE [] { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1) - SWIG_SetPointerZval(*z_var, (void*)$1, $1_descriptor, 0); + if($1) { + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, 0); + } } %typemap(varout) char [ANY] { - zval **z_var; - char *s1; + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + const char *s1 = Z_STRVAL_P(z_var); deliberate error cos this code looks bogus to me - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - s1 = Z_STRVAL_PP(z_var); - if((s1 == NULL) || strcmp(s1, $1)) { - if($1) { - (*z_var)->value.str.val = estrdup($1); - (*z_var)->value.str.len = strlen($1) + 1; + if ((s1 == NULL) || strcmp(s1, $1)) { + if ($1) { + (z_var)->value.str.val = estrdup($1); + (z_var)->value.str.len = strlen($1) + 1; } else { - (*z_var)->value.str.val = 0; - (*z_var)->value.str.len = 0; + (z_var)->value.str.val = 0; + (z_var)->value.str.len = 0; } } } %typemap(varout) SWIGTYPE *, SWIGTYPE &, SWIGTYPE && { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - SWIG_SetPointerZval(*z_var, (void*)$1, $1_descriptor, 0); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, 0); } %typemap(varout, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) { + zval resource; void * p = emalloc(sizeof($1)); memcpy(p, &$1, sizeof($1)); - zval * resource; - MAKE_STD_ZVAL(resource); - ZEND_REGISTER_RESOURCE(resource, p, swig_member_ptr); - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&resource, sizeof(zval *), NULL); + ZVAL_RES(&resource, zend_register_resource(p, swig_member_ptr)); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &resource); } diff --git a/Lib/php/php.swg b/Lib/php/php.swg index 535c7d347..4eba6be2a 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -5,6 +5,7 @@ * ----------------------------------------------------------------------------- */ %runtime "swigrun.swg" // Common C API type-checking code +%runtime "swigerrors.swg" // SWIG errors %runtime "phprun.swg" // PHP runtime functions %include // PHP initialization routine. @@ -71,72 +72,72 @@ // char array can be in/out, though the passed string may not be big enough... // so we have to size it %typemap(in) char[ANY] -{ - convert_to_string_ex($input); - $1 = ($1_ltype) Z_STRVAL_PP($input); -} +%{ + convert_to_string(&$input); + $1 = ($1_ltype) Z_STRVAL($input); +%} -%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) { - convert_to_string_ex($input); - $1 = ($1_ltype) Z_STRVAL_PP($input); - $2 = ($2_ltype) Z_STRLEN_PP($input); -} +%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) %{ + convert_to_string(&$input); + $1 = ($1_ltype) Z_STRVAL($input); + $2 = ($2_ltype) Z_STRLEN($input); +%} /* Object passed by value. Convert to a pointer */ %typemap(in) SWIGTYPE ($&1_ltype tmp) -{ - if(SWIG_ConvertPtr(*$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); } $1 = *tmp; -} +%} %typemap(directorout) SWIGTYPE ($&1_ltype tmp) -{ +%{ /* If exit was via exception, PHP NULL is returned so skip the conversion. */ if (!EG(exception)) { - if(SWIG_ConvertPtr($input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) + if (SWIG_ConvertPtr($input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); $result = *tmp; } -} +%} %typemap(in) SWIGTYPE *, SWIGTYPE [] -{ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } -} +%} %typemap(in) SWIGTYPE & -{ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } -} +%} %typemap(in) SWIGTYPE && -{ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } -} +%} %typemap(in) SWIGTYPE *const& ($*ltype temp) -{ - if(SWIG_ConvertPtr(*$input, (void **) &temp, $*1_descriptor, 0) < 0) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &temp, $*1_descriptor, 0) < 0) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $*1_descriptor"); } $1 = ($1_ltype)&temp; -} +%} %typemap(in) SWIGTYPE *DISOWN -{ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); +%{ + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } -} +%} %typemap(argout) SWIGTYPE *, SWIGTYPE [], @@ -144,14 +145,14 @@ SWIGTYPE &&; %typemap(in) void * -{ - if(SWIG_ConvertPtr(*$input, (void **) &$1, 0, 0) < 0) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &$1, 0, 0) < 0) { /* Allow NULL from php for void* */ - if ((*$input)->type==IS_NULL) $1=0; - else - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); + if (Z_ISNULL($input)) $1=0; + else + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } -} +%} /* Special case when void* is passed by reference so it can be made to point to opaque api structs */ @@ -160,9 +161,9 @@ { /* If they pass NULL by reference, make it into a void* This bit should go in arginit if arginit support init-ing scripting args */ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0) { + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0) { /* So... we didn't get a ref or ptr, but we'll accept NULL by reference */ - if (!((*$input)->type==IS_NULL && PZVAL_IS_REF(*$input))) { + if (!(Z_ISREF($input) && Z_ISNULL_P(Z_REFVAL($input)))) { /* wasn't a pre/ref/thing, OR anything like an int thing */ SWIG_PHP_Error(E_ERROR, "Type error in argument $arg of $symname."); } @@ -181,11 +182,11 @@ } %typemap(argout) void **, void *& -{ +%{ if (force$argnum) { - SWIG_SetPointerZval( *$input, (void*) ptr$argnum, $*1_descriptor, 1); + SWIG_SetPointerZval(&$input, (void*) ptr$argnum, $*1_descriptor, 1); } -} +%} /* Typemap for output values */ @@ -199,35 +200,33 @@ unsigned char, bool, size_t -{ - ZVAL_LONG(return_value,$1); -} +%{ + RETVAL_LONG($1); +%} %typemap(out) enum SWIGTYPE -{ - ZVAL_LONG(return_value, (long)$1); -} +%{ + RETVAL_LONG((long)$1); +%} %typemap(out) long long %{ if ((long long)LONG_MIN <= $1 && $1 <= (long long)LONG_MAX) { - return_value->value.lval = (long)($1); - return_value->type = IS_LONG; + RETVAL_LONG((long)($1)); } else { char temp[256]; sprintf(temp, "%lld", (long long)$1); - ZVAL_STRING(return_value, temp, 1); + RETVAL_STRING(temp); } %} %typemap(out) unsigned long long %{ if ($1 <= (unsigned long long)LONG_MAX) { - return_value->value.lval = (long)($1); - return_value->type = IS_LONG; + RETVAL_LONG((long)($1)); } else { char temp[256]; sprintf(temp, "%llu", (unsigned long long)$1); - ZVAL_STRING(return_value, temp, 1); + RETVAL_STRING(temp); } %} @@ -241,40 +240,38 @@ const unsigned char &, const bool &, const size_t & -{ - ZVAL_LONG(return_value,*$1); -} +%{ + RETVAL_LONG(*$1); +%} %typemap(out) const enum SWIGTYPE & -{ - ZVAL_LONG(return_value, (long)*$1); -} +%{ + RETVAL_LONG((long)*$1); +%} %typemap(out) const enum SWIGTYPE && -{ - ZVAL_LONG(return_value, (long)*$1); -} +%{ + RETVAL_LONG((long)*$1); +%} %typemap(out) const long long & %{ if ((long long)LONG_MIN <= *$1 && *$1 <= (long long)LONG_MAX) { - return_value->value.lval = (long)(*$1); - return_value->type = IS_LONG; + RETVAL_LONG((long)(*$1)); } else { char temp[256]; sprintf(temp, "%lld", (long long)(*$1)); - ZVAL_STRING(return_value, temp, 1); + RETVAL_STRING(temp); } %} %typemap(out) const unsigned long long & %{ if (*$1 <= (unsigned long long)LONG_MAX) { - return_value->value.lval = (long)(*$1); - return_value->type = IS_LONG; + RETVAL_LONG((long)(*$1)); } else { char temp[256]; sprintf(temp, "%llu", (unsigned long long)(*$1)); - ZVAL_STRING(return_value, temp, 1); + RETVAL_STRING(temp); } %} @@ -288,85 +285,85 @@ unsigned char, size_t, enum SWIGTYPE -{ +%{ ZVAL_LONG($input,$1); -} +%} %typemap(directorin) enum SWIGTYPE -{ +%{ ZVAL_LONG($input, (long)$1_name); -} +%} %typemap(directorin) char *, char [] -{ +%{ if(!$1) { ZVAL_NULL($input); } else { - ZVAL_STRING($input, (char *)$1, 1); + ZVAL_STRING($input, (const char*)$1); } -} +%} %typemap(out) bool -{ - ZVAL_BOOL(return_value,($1)?1:0); -} +%{ + RETVAL_BOOL(($1) ? 1 : 0); +%} %typemap(out) const bool & -{ - ZVAL_BOOL(return_value,(*$1)?1:0); -} +%{ + RETVAL_BOOL((*$1) ? 1 : 0); +%} %typemap(directorin) bool -{ - ZVAL_BOOL($input,($1)?1:0); -} +%{ + ZVAL_BOOL($input, ($1) ? 1 : 0); +%} %typemap(out) float, double -{ - ZVAL_DOUBLE(return_value,$1); -} +%{ + RETVAL_DOUBLE($1); +%} %typemap(out) const float &, const double & -{ - ZVAL_DOUBLE(return_value,*$1); -} +%{ + RETVAL_DOUBLE(*$1); +%} %typemap(directorin) float, double -{ - ZVAL_DOUBLE($input,$1); -} +%{ + ZVAL_DOUBLE($input, $1); +%} %typemap(out) char -{ - ZVAL_STRINGL(return_value,&$1, 1, 1); -} +%{ + RETVAL_STRINGL(&$1, 1); +%} %typemap(out) const char & -{ - ZVAL_STRINGL(return_value,&*$1, 1, 1); -} +%{ + RETVAL_STRINGL(&*$1, 1); +%} %typemap(out) char *, char [] -{ - if(!$1) { - ZVAL_NULL(return_value); - } else { - ZVAL_STRING(return_value, (char *)$1, 1); - } -} +%{ + if (!$1) { + RETVAL_NULL(); + } else { + RETVAL_STRING((const char *)$1); + } +%} %typemap(out) char *& -{ - if(!*$1) { - ZVAL_NULL(return_value); - } else { - ZVAL_STRING(return_value, (char *)*$1, 1); - } -} +%{ + if (!*$1) { + RETVAL_NULL(); + } else { + RETVAL_STRING((const char *)*$1); + } +%} %typemap(out) SWIGTYPE *, SWIGTYPE [], @@ -393,12 +390,12 @@ { void * p = emalloc(sizeof($1)); memcpy(p, &$1, sizeof($1)); - ZEND_REGISTER_RESOURCE(return_value, p, swig_member_ptr); + RETVAL_RES(zend_register_resource(p, swig_member_ptr)); } %typemap(in, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) { - void * p = (void*)zend_fetch_resource($input TSRMLS_CC, -1, SWIG_MEMBER_PTR, NULL, 1, swig_member_ptr); + void * p = (void*)zend_fetch_resource_ex(&$input, SWIG_MEMBER_PTR, swig_member_ptr); memcpy(&$1, p, sizeof($1)); } @@ -424,9 +421,9 @@ #endif %typemap(directorin) SWIGTYPE -{ +%{ SWIG_SetPointerZval($input, SWIG_as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&1_descriptor, 1|2); -} +%} %typemap(out) void ""; @@ -434,7 +431,7 @@ { int len = 0; while (len < $1_dim0 && $1[len]) ++len; - RETVAL_STRINGL($1, len, 1); + RETVAL_STRINGL($1, len); } // This typecheck does hard checking for proper argument type. If you want @@ -442,7 +439,13 @@ // it yourself before passing it (e.g. (string)4.7 or (int)"6"). %define %php_typecheck(_type,_prec,is) %typemap(typecheck,precedence=_prec) _type, const _type & - " $1 = (Z_TYPE_PP($input) == is); " + " $1 = (Z_TYPE($input) == is);" +%enddef + +// Like %php_typecheck but allows either of two values. +%define %php_typecheck2(_type,_prec,is1,is2) +%typemap(typecheck,precedence=_prec) _type, const _type & + " $1 = (Z_TYPE($input) == is1 || Z_TYPE($input) == is2);" %enddef %php_typecheck(int,SWIG_TYPECHECK_INTEGER,IS_LONG) @@ -457,41 +460,47 @@ %php_typecheck(unsigned char,SWIG_TYPECHECK_UINT8,IS_LONG) %php_typecheck(size_t,SWIG_TYPECHECK_SIZE,IS_LONG) %php_typecheck(enum SWIGTYPE,SWIG_TYPECHECK_INTEGER,IS_LONG) -%php_typecheck(bool,SWIG_TYPECHECK_BOOL,IS_BOOL) +%php_typecheck2(bool,SWIG_TYPECHECK_BOOL,IS_TRUE,IS_FALSE) %php_typecheck(float,SWIG_TYPECHECK_FLOAT,IS_DOUBLE) %php_typecheck(double,SWIG_TYPECHECK_DOUBLE,IS_DOUBLE) %php_typecheck(char,SWIG_TYPECHECK_CHAR,IS_STRING) %typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) char *, char *&, char [] - " $1 = (Z_TYPE_PP($input) == IS_STRING); " + " $1 = (Z_TYPE($input) == IS_STRING); " %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { void *tmp; - _v = (SWIG_ConvertPtr(*$input, (void **)&tmp, $&1_descriptor, 0) >= 0); + $1 = (SWIG_ConvertPtr(&$input, (void **)&tmp, $&1_descriptor, SWIG_POINTER_NO_NULL) >= 0); } %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE [], - SWIGTYPE &, - SWIGTYPE &&, SWIGTYPE *const& { void *tmp; - _v = (SWIG_ConvertPtr(*$input, (void**)&tmp, $1_descriptor, 0) >= 0); + $1 = (SWIG_ConvertPtr(&$input, (void**)&tmp, $1_descriptor, 0) >= 0); +} + +%typecheck(SWIG_TYPECHECK_POINTER) + SWIGTYPE &, + SWIGTYPE && +{ + void *tmp; + $1 = (SWIG_ConvertPtr(&$input, (void**)&tmp, $1_descriptor, SWIG_POINTER_NO_NULL) >= 0); } %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *const& { void *tmp; - _v = (SWIG_ConvertPtr(*$input, (void**)&tmp, $*1_descriptor, 0) >= 0); + $1 = (SWIG_ConvertPtr(&$input, (void**)&tmp, $*1_descriptor, 0) >= 0); } %typecheck(SWIG_TYPECHECK_VOIDPTR) void * { void *tmp; - _v = (SWIG_ConvertPtr(*$input, (void**)&tmp, 0, 0) >= 0); + $1 = (SWIG_ConvertPtr(&$input, (void**)&tmp, 0, 0) >= 0); } /* Exception handling */ @@ -501,19 +510,19 @@ short, unsigned int, unsigned long, - unsigned short { - zend_throw_exception(NULL, const_cast("C++ $1_type exception thrown"), $1 TSRMLS_CC); + unsigned short %{ + zend_throw_exception(NULL, "C++ $1_type exception thrown", $1); return; -} +%} %typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE *, SWIGTYPE [], SWIGTYPE [ANY] %{ (void)$1; - zend_throw_exception(NULL, const_cast("C++ $1_type exception thrown"), 0 TSRMLS_CC); + zend_throw_exception(NULL, "C++ $1_type exception thrown", 0); return; %} %typemap(throws) char * %{ - zend_throw_exception(NULL, const_cast($1), 0 TSRMLS_CC); + zend_throw_exception(NULL, $1, 0); return; %} @@ -523,7 +532,8 @@ /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } - +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } /* php keywords */ %include diff --git a/Lib/php/phpinit.swg b/Lib/php/phpinit.swg index 6e5cc29d2..1665f5dc4 100644 --- a/Lib/php/phpinit.swg +++ b/Lib/php/phpinit.swg @@ -1,25 +1,25 @@ /* ------------------------------------------------------------ - * The start of the PHP initialization function + * The start of the PHP initialization function * ------------------------------------------------------------ */ %insert(init) "swiginit.swg" %init %{ - SWIG_php_minit { - SWIG_InitializeModule(0); +SWIG_php_minit { + SWIG_InitializeModule((void*)&module_number); %} -%fragment("swig_php_init_member_ptr2", "header") { -#define SWIG_MEMBER_PTR ((char*)"CLASS::*") +%fragment("swig_php_init_member_ptr2", "header") %{ +#define SWIG_MEMBER_PTR "CLASS::*" -static void swig_member_ptr_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) { - efree(rsrc->ptr); +static void swig_member_ptr_dtor(zend_resource *res) { + efree(res->ptr); } static int swig_member_ptr = 0; -} +%} -%fragment("swig_php_init_member_ptr", "init", fragment="swig_php_init_member_ptr2") { - swig_member_ptr = zend_register_list_destructors_ex(swig_member_ptr_dtor, NULL, SWIG_MEMBER_PTR, module_number); -} +%fragment("swig_php_init_member_ptr", "init", fragment="swig_php_init_member_ptr2") %{ + swig_member_ptr = zend_register_list_destructors_ex(swig_member_ptr_dtor, NULL, SWIG_MEMBER_PTR, module_number); +%} diff --git a/Lib/php/phpkw.swg b/Lib/php/phpkw.swg index 36e535f52..5c5296a1f 100644 --- a/Lib/php/phpkw.swg +++ b/Lib/php/phpkw.swg @@ -30,13 +30,11 @@ * could lead to confusion." */ /* Check is case insensitive - these *MUST* be listed in lower case here */ -PHPKW(__halt_compiler); PHPKW(abstract); PHPKW(and); -PHPKW(array); PHPKW(as); PHPKW(break); -PHPKW(callable); // As of PHP 5.4 +PHPKW(callable); PHPKW(case); PHPKW(catch); PHPKW(class); @@ -45,71 +43,57 @@ PHPKW(const); PHPKW(continue); PHPKW(declare); PHPKW(default); -PHPKW(die); // "Language construct" PHPKW(do); -PHPKW(echo); // "Language construct" PHPKW(else); PHPKW(elseif); -PHPKW(empty); // "Language construct" PHPKW(enddeclare); PHPKW(endfor); PHPKW(endforeach); PHPKW(endif); PHPKW(endswitch); PHPKW(endwhile); -PHPKW(eval); // "Language construct" -PHPKW(exit); // "Language construct" PHPKW(extends); PHPKW(final); -PHPKW(finally); // As of PHP 5.5 +PHPKW(finally); PHPKW(for); PHPKW(foreach); PHPKW(function); PHPKW(global); -PHPKW(goto); // As of PHP 5.3 +PHPKW(goto); PHPKW(if); PHPKW(implements); -PHPKW(include); // "Language construct" -PHPKW(include_once); // "Language construct" PHPKW(instanceof); -PHPKW(insteadof); // As of PHP 5.4 +PHPKW(insteadof); PHPKW(interface); -PHPKW(isset); // "Language construct" -PHPKW(list); // "Language construct" -PHPKW(namespace); // As of PHP 5.3 +PHPKW(namespace); PHPKW(new); PHPKW(or); -PHPKW(print); // "Language construct" PHPKW(private); PHPKW(protected); PHPKW(public); -PHPKW(require); // "Language construct" -PHPKW(require_once); // "Language construct" -PHPKW(return); // "Language construct" PHPKW(static); PHPKW(switch); PHPKW(throw); -PHPKW(trait); // As of PHP 5.4 +PHPKW(trait); PHPKW(try); -PHPKW(unset); // "Language construct" PHPKW(use); PHPKW(var); PHPKW(while); PHPKW(xor); -PHPKW(yield); // As of PHP 5.5 +PHPKW(yield); // Compile-time "magic" constants // From: http://php.net/manual/en/reserved.keywords.php // also at: http://php.net/manual/en/language.constants.predefined.php /* These *MUST* be listed in lower case here */ PHPKW(__class__); -PHPKW(__dir__); // As of PHP 5.3 +PHPKW(__dir__); PHPKW(__file__); PHPKW(__function__); PHPKW(__line__); PHPKW(__method__); -PHPKW(__namespace__); // As of PHP 5.3 -PHPKW(__trait__); // As of PHP 5.4 +PHPKW(__namespace__); +PHPKW(__trait__); /* We classify these as built-in names since they conflict, but PHP still runs */ @@ -122,27 +106,27 @@ PHPBN1(false); /* "Core Predefined Constants" from http://php.net/manual/en/reserved.constants.php */ /* These are case sensitive */ PHPBN2(PHP_VERSION); -PHPBN2(PHP_MAJOR_VERSION); // As of PHP 5.2.7 -PHPBN2(PHP_MINOR_VERSION); // As of PHP 5.2.7 -PHPBN2(PHP_RELEASE_VERSION); // As of PHP 5.2.7 -PHPBN2(PHP_VERSION_ID); // As of PHP 5.2.7 -PHPBN2(PHP_EXTRA_VERSION); // As of PHP 5.2.7 -PHPBN2(PHP_ZTS); // As of PHP 5.2.7 -PHPBN2(PHP_DEBUG); // As of PHP 5.2.7 -PHPBN2(PHP_MAXPATHLEN); // As of PHP 5.3.0 +PHPBN2(PHP_MAJOR_VERSION); +PHPBN2(PHP_MINOR_VERSION); +PHPBN2(PHP_RELEASE_VERSION); +PHPBN2(PHP_VERSION_ID); +PHPBN2(PHP_EXTRA_VERSION); +PHPBN2(PHP_ZTS); +PHPBN2(PHP_DEBUG); +PHPBN2(PHP_MAXPATHLEN); PHPBN2(PHP_OS); PHPBN2(PHP_SAPI); -PHPBN2(PHP_EOL); // As of PHP 5.0.2 -PHPBN2(PHP_INT_MAX); // As of PHP 5.0.5 -PHPBN2(PHP_INT_SIZE); // As of PHP 5.0.5 +PHPBN2(PHP_EOL); +PHPBN2(PHP_INT_MAX); +PHPBN2(PHP_INT_SIZE); PHPBN2(DEFAULT_INCLUDE_PATH); PHPBN2(PEAR_INSTALL_DIR); PHPBN2(PEAR_EXTENSION_DIR); PHPBN2(PHP_EXTENSION_DIR); PHPBN2(PHP_PREFIX); PHPBN2(PHP_BINDIR); -PHPBN2(PHP_BINARY); // As of PHP 5.4 -PHPBN2(PHP_MANDIR); // As of PHP 5.3.7 +PHPBN2(PHP_BINARY); +PHPBN2(PHP_MANDIR); PHPBN2(PHP_LIBDIR); PHPBN2(PHP_DATADIR); PHPBN2(PHP_SYSCONFDIR); @@ -161,11 +145,11 @@ PHPBN2(E_COMPILE_WARNING); PHPBN2(E_USER_ERROR); PHPBN2(E_USER_WARNING); PHPBN2(E_USER_NOTICE); -PHPBN2(E_DEPRECATED); // As of PHP 5.3.0 -PHPBN2(E_USER_DEPRECATED); // As of PHP 5.3.0 +PHPBN2(E_DEPRECATED); +PHPBN2(E_USER_DEPRECATED); PHPBN2(E_ALL); PHPBN2(E_STRICT); -PHPBN2(__COMPILER_HALT_OFFSET__); // As of PHP 5.1.0 +PHPBN2(__COMPILER_HALT_OFFSET__); // TRUE, FALSE, NULL are listed on the same page, but are actually // case-insensitive, whereas all the other constants listed there seem to be // case-sensitive, so we handle TRUE, FALSE, NULL in PHPBN1. @@ -174,17 +158,17 @@ PHPBN2(PHP_OUTPUT_HANDLER_CONT); PHPBN2(PHP_OUTPUT_HANDLER_END); /* These don't actually seem to be set (tested on Linux, I guess they're * Windows only?) */ -PHPBN2(PHP_WINDOWS_NT_DOMAIN_CONTROLLER); // As of PHP 5.3 -PHPBN2(PHP_WINDOWS_NT_SERVER); // As of PHP 5.3 -PHPBN2(PHP_WINDOWS_NT_WORKSTATION); // As of PHP 5.3 -PHPBN2(PHP_WINDOWS_VERSION_BUILD); // As of PHP 5.3 -PHPBN2(PHP_WINDOWS_VERSION_MAJOR); // As of PHP 5.3 -PHPBN2(PHP_WINDOWS_VERSION_MINOR); // As of PHP 5.3 -PHPBN2(PHP_WINDOWS_VERSION_PLATFORM); // As of PHP 5.3 -PHPBN2(PHP_WINDOWS_VERSION_PRODUCTTYPE); // As of PHP 5.3 -PHPBN2(PHP_WINDOWS_VERSION_SP_MAJOR); // As of PHP 5.3 -PHPBN2(PHP_WINDOWS_VERSION_SP_MINOR); // As of PHP 5.3 -PHPBN2(PHP_WINDOWS_VERSION_SUITEMASK); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_NT_DOMAIN_CONTROLLER); +PHPBN2(PHP_WINDOWS_NT_SERVER); +PHPBN2(PHP_WINDOWS_NT_WORKSTATION); +PHPBN2(PHP_WINDOWS_VERSION_BUILD); +PHPBN2(PHP_WINDOWS_VERSION_MAJOR); +PHPBN2(PHP_WINDOWS_VERSION_MINOR); +PHPBN2(PHP_WINDOWS_VERSION_PLATFORM); +PHPBN2(PHP_WINDOWS_VERSION_PRODUCTTYPE); +PHPBN2(PHP_WINDOWS_VERSION_SP_MAJOR); +PHPBN2(PHP_WINDOWS_VERSION_SP_MINOR); +PHPBN2(PHP_WINDOWS_VERSION_SUITEMASK); /* "Standard Predefined Constants" from http://php.net/manual/en/reserved.constants.php */ PHPBN2(EXTR_OVERWRITE); PHPBN2(EXTR_SKIP); @@ -214,8 +198,8 @@ PHPBN2(INI_USER); PHPBN2(INI_PERDIR); PHPBN2(INI_SYSTEM); PHPBN2(INI_ALL); -PHPBN2(INI_SCANNER_NORMAL); // As of PHP 5.3 -PHPBN2(INI_SCANNER_RAW); // As of PHP 5.3 +PHPBN2(INI_SCANNER_NORMAL); +PHPBN2(INI_SCANNER_RAW); PHPBN2(M_E); PHPBN2(M_LOG2E); PHPBN2(M_LOG10E); @@ -229,10 +213,10 @@ PHPBN2(M_2_PI); PHPBN2(M_2_SQRTPI); PHPBN2(M_SQRT2); PHPBN2(M_SQRT1_2); -PHPBN2(M_EULER); // As of PHP 5.2 -PHPBN2(M_LNPI); // As of PHP 5.2 -PHPBN2(M_SQRT3); // As of PHP 5.2 -PHPBN2(M_SQRTPI); // As of PHP 5.2 +PHPBN2(M_EULER); +PHPBN2(M_LNPI); +PHPBN2(M_SQRT3); +PHPBN2(M_SQRTPI); PHPBN2(CRYPT_SALT_LENGTH); PHPBN2(CRYPT_STD_DES); PHPBN2(CRYPT_EXT_DES); @@ -273,7 +257,7 @@ PHPBN2(STR_PAD_BOTH); PHPBN2(PATHINFO_DIRNAME); PHPBN2(PATHINFO_BASENAME); PHPBN2(PATHINFO_EXTENSION); -PHPBN2(PATHINFO_FILENAME); // As of PHP 5.2 +PHPBN2(PATHINFO_FILENAME); PHPBN2(PATH_SEPARATOR); PHPBN2(CHAR_MAX); PHPBN2(LC_CTYPE); @@ -393,7 +377,6 @@ PHPBN2(LOG_NDELAY); PHPBN2(LOG_NOWAIT); PHPBN2(LOG_PERROR); -/* Added in PHP 5.2 */ PHPBN2(PREG_BACKTRACK_LIMIT_ERROR); PHPBN2(PREG_BAD_UTF8_ERROR); PHPBN2(PREG_INTERNAL_ERROR); @@ -415,10 +398,10 @@ PHPBN2(CURLFTPSSL_NONE); PHPBN2(CURLFTPSSL_TRY); PHPBN2(CURLOPT_FTP_SSL); PHPBN2(CURLOPT_FTPSSLAUTH); -PHPBN2(CURLOPT_TCP_NODELAY); // Added in PHP 5.2.1 -PHPBN2(CURLOPT_TIMEOUT_MS); // Added in PHP 5.2.3 -PHPBN2(CURLOPT_CONNECTTIMEOUT_MS); // Added in PHP 5.2.3 -PHPBN2(GMP_VERSION); // Added in PHP 5.2.2 +PHPBN2(CURLOPT_TCP_NODELAY); +PHPBN2(CURLOPT_TIMEOUT_MS); +PHPBN2(CURLOPT_CONNECTTIMEOUT_MS); +PHPBN2(GMP_VERSION); PHPBN2(SWFTEXTFIELD_USEFONT); PHPBN2(SWFTEXTFIELD_AUTOSIZE); PHPBN2(SWF_SOUND_NOT_COMPRESSED); @@ -440,7 +423,6 @@ PHPBN2(SNMP_OID_OUTPUT_NUMERIC); PHPBN2(MSG_EAGAIN); PHPBN2(MSG_ENOMSG); -/* Added in PHP 5.3 */ PHPBN2(CURLOPT_PROGRESSFUNCTION); PHPBN2(IMG_FILTER_PIXELATE); PHPBN2(JSON_ERROR_CTRL_CHAR); @@ -504,7 +486,6 @@ PHPBN2(SIG_UNBLOCK); PHPBN2(TRAP_BRKPT); PHPBN2(TRAP_TRACE); -/* Added in PHP 5.4 */ PHPBN2(ENT_DISALLOWED); PHPBN2(ENT_HTML401); PHPBN2(ENT_HTML5); @@ -583,7 +564,6 @@ PHPBN2(JSON_NUMERIC_CHECK); PHPBN2(JSON_UNESCAPED_UNICODE); PHPBN2(JSON_BIGINT_AS_STRING); -/* Added in PHP 5.5 */ PHPBN2(IMG_AFFINE_TRANSLATE); PHPBN2(IMG_AFFINE_SCALE); PHPBN2(IMG_AFFINE_ROTATE); @@ -622,7 +602,6 @@ PHPBN2(JSON_ERROR_INF_OR_NAN); PHPBN2(JSON_ERROR_UNSUPPORTED_TYPE); PHPBN2(MYSQLI_SERVER_PUBLIC_KEY); -/* Added in PHP 5.6 */ PHPBN2(LDAP_ESCAPE_DN); PHPBN2(LDAP_ESCAPE_FILTER); PHPBN2(OPENSSL_DEFAULT_STREAM_CIPHERS); @@ -654,13 +633,28 @@ PHPCN(stdclass); PHPCN(__php_incomplete_class); /* Added in PHP5. */ PHPCN(exception); -PHPCN(errorexception); // As of PHP 5.1 +PHPCN(errorexception); PHPCN(php_user_filter); -PHPCN(closure); // As of PHP 5.3 -PHPCN(generator); // As of PHP 5.5 +PHPCN(closure); +PHPCN(generator); PHPCN(self); PHPCN(static); PHPCN(parent); +/* http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.other.classes */ +PHPCN(bool); // As of PHP 7.0 +PHPCN(int); // As of PHP 7.0 +PHPCN(float); // As of PHP 7.0 +PHPCN(string); // As of PHP 7.0 +PHPCN(NULL); // As of PHP 7.0 +PHPCN(TRUE); // As of PHP 7.0 +PHPCN(FALSE); // As of PHP 7.0 +PHPCN(resource); // As of PHP 7.0 (currently works but reserved) +PHPCN(object); // As of PHP 7.0 (currently works but reserved) +PHPCN(mixed); // As of PHP 7.0 (currently works but reserved) +PHPCN(numeric); // As of PHP 7.0 (currently works but reserved) +/* http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.invalid-class-names */ +PHPCN(iterable); // As of PHP 7.1 +PHPCN(void); // As of PHP 7.1 /* From extensions (which of these are actually predefined depends which * extensions are loaded by default). */ PHPCN(xmlwriter); @@ -757,7 +751,9 @@ PHPCN(datetime); /* Built-in PHP functions (incomplete). */ /* Includes Array Functions - http://php.net/manual/en/ref.array.php */ /* Check is case insensitive - these *MUST* be listed in lower case here */ +PHPFN(__halt_compiler); PHPFN(acos); +PHPFN(array); PHPFN(array_change_key_case); PHPFN(array_chunk); PHPFN(array_column); @@ -819,17 +815,26 @@ PHPFN(cos); PHPFN(cosh); PHPFN(count); PHPFN(current); +PHPFN(die); // "Language construct" PHPFN(each); +PHPFN(echo); // "Language construct" +PHPFN(empty); PHPFN(end); +PHPFN(eval); // "Language construct" +PHPFN(exit); // "Language construct" PHPFN(exp); PHPFN(extract); PHPFN(floor); PHPFN(fmod); PHPFN(in_array); +PHPFN(include); // "Language construct" +PHPFN(include_once); // "Language construct" +PHPFN(isset); // "Language construct" PHPFN(key); PHPFN(key_exists); PHPFN(krsort); PHPFN(ksort); +PHPFN(list); // "Language construct" PHPFN(log); PHPFN(log10); PHPFN(max); @@ -840,9 +845,13 @@ PHPFN(next); PHPFN(pos); PHPFN(pow); PHPFN(prev); +PHPFN(print); // "Language construct" PHPFN(range); PHPFN(reset); PHPFN(rsort); +PHPFN(require); // "Language construct" +PHPFN(require_once); // "Language construct" +PHPFN(return); // "Language construct" PHPFN(shuffle); PHPFN(sin); PHPFN(sinh); @@ -853,6 +862,7 @@ PHPFN(tan); PHPFN(tanh); PHPFN(uasort); PHPFN(uksort); +PHPFN(unset); // "Language construct" PHPFN(usort); #undef PHPKW diff --git a/Lib/php/phppointers.i b/Lib/php/phppointers.i index e50ada7ac..d79697b5e 100644 --- a/Lib/php/phppointers.i +++ b/Lib/php/phppointers.i @@ -3,19 +3,23 @@ TYPE &REF ($*1_ltype tmp) %{ /* First Check for SWIG wrapped type */ - if ( ZVAL_IS_NULL( *$input ) ) { + if (Z_ISNULL($input)) { $1 = 0; - } else if ( PZVAL_IS_REF( *$input ) ) { + } else if (Z_ISREF($input)) { /* Not swig wrapped type, so we check if it's a PHP reference type */ - CONVERT_IN( tmp, $*1_ltype, $input ); + CONVERT_IN(tmp, $*1_ltype, $input); $1 = &tmp; } else { - SWIG_PHP_Error( E_ERROR, SWIG_PHP_Arg_Error_Msg($argnum, Expected a reference) ); + SWIG_PHP_Error(E_ERROR, SWIG_PHP_Arg_Error_Msg($argnum, Expected a reference)); } %} %typemap(argout) TYPE *REF, TYPE &REF - "CONVERT_OUT(*$input, tmp$argnum );"; +%{ + if (Z_ISREF($input)) { + CONVERT_OUT(Z_REFVAL($input), tmp$argnum); + } +%} %enddef %pass_by_ref( size_t, CONVERT_INT_IN, ZVAL_LONG ); diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index 0021a90e8..a07a1b9f8 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -11,65 +11,38 @@ extern "C" { #include "zend_API.h" #include "zend_exceptions.h" #include "php.h" + +#if PHP_MAJOR_VERSION != 7 +# error These bindings need PHP7 - to generate PHP5 bindings use: SWIG < 4.0.0 and swig -php5 +#endif + #include "ext/standard/php_string.h" #include /* for abort(), used in generated code. */ -#ifdef ZEND_RAW_FENTRY -/* ZEND_RAW_FENTRY was added somewhere between 5.2.0 and 5.2.3 */ -# define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_RAW_FENTRY((char*)#ZN, N, A, 0) -#else -/* This causes warnings from GCC >= 4.2 (assigning a string literal to char*). - * But this seems to be unavoidable without directly assuming knowledge of - * the structure, which changed between PHP4 and PHP5. */ -# define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_NAMED_FE(ZN, N, A) -#endif +/* This indirection is to work around const correctness issues in older PHP. + * FIXME: Remove for PHP7? Or might user code be using it? */ +#define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_NAMED_FE(ZN, N, A) -#ifndef ZEND_FE_END -# define ZEND_FE_END { NULL, NULL, NULL } -#endif - -#ifndef Z_SET_ISREF_P -/* For PHP < 5.3 */ -# define Z_SET_ISREF_P(z) (z)->is_ref = 1 -#endif -#ifndef Z_SET_REFCOUNT_P -/* For PHP < 5.3 */ -# define Z_SET_REFCOUNT_P(z, rc) (z)->refcount = (rc) -#endif - -#define SWIG_LONG_CONSTANT(N, V) zend_register_long_constant((char*)#N, sizeof(#N), V, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) -#define SWIG_DOUBLE_CONSTANT(N, V) zend_register_double_constant((char*)#N, sizeof(#N), V, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) -#define SWIG_STRING_CONSTANT(N, V) zend_register_stringl_constant((char*)#N, sizeof(#N), (char*)(V), strlen(V), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) +#define SWIG_BOOL_CONSTANT(N, V) REGISTER_BOOL_CONSTANT(#N, V, CONST_CS | CONST_PERSISTENT) +#define SWIG_LONG_CONSTANT(N, V) REGISTER_LONG_CONSTANT(#N, V, CONST_CS | CONST_PERSISTENT) +#define SWIG_DOUBLE_CONSTANT(N, V) REGISTER_DOUBLE_CONSTANT(#N, V, CONST_CS | CONST_PERSISTENT) +#define SWIG_STRING_CONSTANT(N, V) REGISTER_STRING_CONSTANT(#N, (char*)V, CONST_CS | CONST_PERSISTENT) #define SWIG_CHAR_CONSTANT(N, V) do {\ - static char swig_char = (V);\ - zend_register_stringl_constant((char*)#N, sizeof(#N), &swig_char, 1, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);\ + char swig_char = (V);\ + REGISTER_STRINGL_CONSTANT(#N, &swig_char, 1, CONST_CS | CONST_PERSISTENT);\ } while (0) -/* These TSRMLS_ stuff should already be defined now, but with older php under - redhat are not... */ -#ifndef TSRMLS_D -#define TSRMLS_D -#endif -#ifndef TSRMLS_DC -#define TSRMLS_DC -#endif -#ifndef TSRMLS_C -#define TSRMLS_C -#endif -#ifndef TSRMLS_CC -#define TSRMLS_CC +/* ZEND_CONSTANT_SET_FLAGS is new in PHP 7.3. */ +#ifdef ZEND_CONSTANT_SET_FLAGS +# define SWIG_ZEND_CONSTANT_SET_FLAGS ZEND_CONSTANT_SET_FLAGS +#else +# define SWIG_ZEND_CONSTANT_SET_FLAGS(C, F, N) do { (C)->flags = (F); (C)->module_number = (N); } while (0) #endif #ifdef __cplusplus } #endif -/* But in fact SWIG_ConvertPtr is the native interface for getting typed - pointer values out of zvals. We need the TSRMLS_ macros for when we - make PHP type calls later as we handle php resources */ -#define SWIG_ConvertPtr(obj,pp,type,flags) SWIG_ZTS_ConvertPtr(obj,pp,type,flags TSRMLS_CC) - - #define SWIG_fail goto fail static const char *default_error_msg = "Unknown error occurred"; @@ -84,7 +57,7 @@ static int default_error_code = E_ERROR; /* Standard SWIG API */ #define SWIG_GetModule(clientdata) SWIG_Php_GetModule() -#define SWIG_SetModule(clientdata, pointer) SWIG_Php_SetModule(pointer) +#define SWIG_SetModule(clientdata, pointer) SWIG_Php_SetModule(pointer, *(int*)clientdata) /* used to wrap returned objects in so we know whether they are newobject and need freeing, or not */ @@ -93,11 +66,10 @@ typedef struct { int newobject; } swig_object_wrapper; -#define SWIG_SetPointerZval(a,b,c,d) SWIG_ZTS_SetPointerZval(a,b,c,d TSRMLS_CC) #define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) static void -SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject TSRMLS_DC) { +SWIG_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject) { /* * First test for Null pointers. Return those as PHP native NULL */ @@ -114,19 +86,19 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject value->newobject=(newobject & 1); if ((newobject & 2) == 0) { /* Just register the pointer as a resource. */ - ZEND_REGISTER_RESOURCE(z, value, *(int *)(type->clientdata)); + ZVAL_RES(z, zend_register_resource(value, *(int *)(type->clientdata))); } else { /* * Wrap the resource in an object, the resource will be accessible * via the "_cPtr" member. This is currently only used by * directorin typemaps. */ - zval *resource; - zend_class_entry **ce = NULL; + zval resource; + zend_class_entry *ce = NULL; const char *type_name = type->name+3; /* +3 so: _p_Foo -> Foo */ size_t type_name_len; - int result; const char * p; + HashTable * ht; /* Namespace__Foo -> Foo */ /* FIXME: ugly and goes wrong for classes with __ in their names. */ @@ -135,26 +107,27 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject } type_name_len = strlen(type_name); - MAKE_STD_ZVAL(resource); - ZEND_REGISTER_RESOURCE(resource, value, *(int *)(type->clientdata)); + ZVAL_RES(&resource, zend_register_resource(value, *(int *)(type->clientdata))); if (SWIG_PREFIX_LEN > 0) { - char * classname = (char*)emalloc(SWIG_PREFIX_LEN + type_name_len + 1); - strcpy(classname, SWIG_PREFIX); - strcpy(classname + SWIG_PREFIX_LEN, type_name); - result = zend_lookup_class(classname, SWIG_PREFIX_LEN + type_name_len, &ce TSRMLS_CC); - efree(classname); + zend_string * classname = zend_string_alloc(SWIG_PREFIX_LEN + type_name_len, 0); + memcpy(classname->val, SWIG_PREFIX, SWIG_PREFIX_LEN); + memcpy(classname->val + SWIG_PREFIX_LEN, type_name, type_name_len); + ce = zend_lookup_class(classname); + zend_string_release(classname); } else { - result = zend_lookup_class((char *)type_name, type_name_len, &ce TSRMLS_CC); + zend_string * classname = zend_string_init(type_name, type_name_len, 0); + ce = zend_lookup_class(classname); + zend_string_release(classname); } - if (result != SUCCESS) { + if (ce == NULL) { /* class does not exist */ - object_init(z); - } else { - object_init_ex(z, *ce); + ce = zend_standard_class_def; } - Z_SET_REFCOUNT_P(z, 1); - Z_SET_ISREF_P(z); - zend_hash_update(HASH_OF(z), (char*)"_cPtr", sizeof("_cPtr"), (void*)&resource, sizeof(zval*), NULL); + + ALLOC_HASHTABLE(ht); + zend_hash_init(ht, 1, NULL, NULL, 0); + zend_hash_str_update(ht, "_cPtr", sizeof("_cPtr") - 1, &resource); + object_and_properties_init(z, ce, ht); } return; } @@ -170,11 +143,11 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject instance of a resource of the type id, so we have to pass type_name as well. The two functions which might call this are: - SWIG_ZTS_ConvertResourcePtr which gets the type name from the resource + SWIG_ConvertResourcePtr which gets the type name from the resource and the registered zend destructors for which we have one per type each with the type name hard wired in. */ static void * -SWIG_ZTS_ConvertResourceData(void * p, const char *type_name, swig_type_info *ty TSRMLS_DC) { +SWIG_ConvertResourceData(void * p, const char *type_name, swig_type_info *ty) { swig_cast_info *tc; void *result = 0; @@ -201,75 +174,73 @@ SWIG_ZTS_ConvertResourceData(void * p, const char *type_name, swig_type_info *ty /* This function returns a pointer of type ty by extracting the pointer and type info from the resource in z. z must be a resource. If it fails, NULL is returned. - It uses SWIG_ZTS_ConvertResourceData to do the real work. */ + It uses SWIG_ConvertResourceData to do the real work. */ static void * -SWIG_ZTS_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags TSRMLS_DC) { +SWIG_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags) { swig_object_wrapper *value; void *p; - int type; const char *type_name; - value = (swig_object_wrapper *) zend_list_find(z->value.lval, &type); - if (type==-1) return NULL; + if (Z_RES_TYPE_P(z) == -1) return NULL; + value = (swig_object_wrapper *) Z_RES_VAL_P(z); if (flags & SWIG_POINTER_DISOWN) { value->newobject = 0; } p = value->ptr; - type_name=zend_rsrc_list_get_rsrc_type(z->value.lval TSRMLS_CC); + type_name=zend_rsrc_list_get_rsrc_type(Z_RES_P(z)); - return SWIG_ZTS_ConvertResourceData(p, type_name, ty TSRMLS_CC); + return SWIG_ConvertResourceData(p, type_name, ty); } /* We allow passing of a RESOURCE pointing to the object or an OBJECT whose _cPtr is a resource pointing to the object */ static int -SWIG_ZTS_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags TSRMLS_DC) { +SWIG_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags) { if (z == NULL) { *ptr = 0; return 0; } - switch (z->type) { + switch (Z_TYPE_P(z)) { case IS_OBJECT: { - zval ** _cPtr; - if (zend_hash_find(HASH_OF(z),(char*)"_cPtr",sizeof("_cPtr"),(void**)&_cPtr)==SUCCESS) { - if ((*_cPtr)->type==IS_RESOURCE) { - *ptr = SWIG_ZTS_ConvertResourcePtr(*_cPtr, ty, flags TSRMLS_CC); - return (*ptr == NULL ? -1 : 0); - } + HashTable * ht = Z_OBJ_HT_P(z)->get_properties(z); + if (ht) { + zval * _cPtr = zend_hash_str_find(ht, "_cPtr", sizeof("_cPtr") - 1); + if (_cPtr) { + if (Z_TYPE_P(_cPtr) == IS_INDIRECT) { + _cPtr = Z_INDIRECT_P(_cPtr); + } + if (Z_TYPE_P(_cPtr) == IS_RESOURCE) { + *ptr = SWIG_ConvertResourcePtr(_cPtr, ty, flags); + return (*ptr == NULL ? -1 : 0); + } + } } break; } case IS_RESOURCE: - *ptr = SWIG_ZTS_ConvertResourcePtr(z, ty, flags TSRMLS_CC); + *ptr = SWIG_ConvertResourcePtr(z, ty, flags); return (*ptr == NULL ? -1 : 0); case IS_NULL: *ptr = 0; - return 0; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } return -1; } -static char const_name[] = "swig_runtime_data_type_pointer"; +static const char const_name[] = "swig_runtime_data_type_pointer"; static swig_module_info *SWIG_Php_GetModule() { - zval *pointer; - swig_module_info *ret = 0; - TSRMLS_FETCH(); - - MAKE_STD_ZVAL(pointer); - - if (zend_get_constant(const_name, sizeof(const_name) - 1, pointer TSRMLS_CC)) { - if (pointer->type == IS_LONG) { - ret = (swig_module_info *) pointer->value.lval; + zval *pointer = zend_get_constant_str(const_name, sizeof(const_name) - 1); + if (pointer) { + if (Z_TYPE_P(pointer) == IS_LONG) { + return (swig_module_info *) pointer->value.lval; } } - FREE_ZVAL(pointer); - return ret; + return NULL; } -static void SWIG_Php_SetModule(swig_module_info *pointer) { - TSRMLS_FETCH(); - REGISTER_MAIN_LONG_CONSTANT(const_name, (long) pointer, 0); +static void SWIG_Php_SetModule(swig_module_info *pointer, int module_number) { + REGISTER_LONG_CONSTANT(const_name, (long) pointer, CONST_CS | CONST_PERSISTENT); } diff --git a/Lib/php/std_map.i b/Lib/php/std_map.i index 6d5e3db13..7c0157353 100644 --- a/Lib/php/std_map.i +++ b/Lib/php/std_map.i @@ -20,21 +20,27 @@ namespace std { - template class map { + template > class map { // add typemaps here public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; void clear(); %extend { const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -44,14 +50,14 @@ namespace std { (*self)[key] = x; } void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } bool is_empty() const { diff --git a/Lib/php/std_pair.i b/Lib/php/std_pair.i index fe45ee676..732347db5 100644 --- a/Lib/php/std_pair.i +++ b/Lib/php/std_pair.i @@ -18,12 +18,14 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/php/std_string.i b/Lib/php/std_string.i index aaa5dc9cd..b55751f07 100644 --- a/Lib/php/std_string.i +++ b/Lib/php/std_string.i @@ -24,53 +24,68 @@ namespace std { class string; %typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) string, const string& %{ - $1 = ( Z_TYPE_PP($input) == IS_STRING ) ? 1 : 0; + $1 = (Z_TYPE($input) == IS_STRING) ? 1 : 0; %} %typemap(in) string %{ - convert_to_string_ex($input); - $1.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input)); + convert_to_string(&$input); + $1.assign(Z_STRVAL($input), Z_STRLEN($input)); %} %typemap(directorout) string %{ - convert_to_string_ex(&$input); + if (!EG(exception)) { + convert_to_string($input); $result.assign(Z_STRVAL_P($input), Z_STRLEN_P($input)); + } %} %typemap(out) string %{ - ZVAL_STRINGL($result, const_cast($1.data()), $1.size(), 1); + ZVAL_STRINGL($result, $1.data(), $1.size()); %} %typemap(directorin) string, const string& %{ - ZVAL_STRINGL($input, const_cast($1.data()), $1.size(), 1); + ZVAL_STRINGL($input, $1.data(), $1.size()); %} %typemap(out) const string & %{ - ZVAL_STRINGL($result, const_cast($1->data()), $1->size(), 1); + ZVAL_STRINGL($result, $1->data(), $1->size()); %} %typemap(throws) string, const string& %{ - zend_throw_exception(NULL, const_cast($1.c_str()), 0 TSRMLS_CC); + zend_throw_exception(NULL, $1.c_str(), 0); return; %} + %typemap(in) const string & ($*1_ltype temp) %{ + convert_to_string(&$input); + temp.assign(Z_STRVAL($input), Z_STRLEN($input)); + $1 = &temp; + %} + /* These next two handle a function which takes a non-const reference to * a std::string and modifies the string. */ - %typemap(in) string & ($*1_ltype temp) %{ - convert_to_string_ex($input); - temp.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input)); - $1 = &temp; + %typemap(in,byref=1) string & ($*1_ltype temp) %{ + { + zval * p = Z_ISREF($input) ? Z_REFVAL($input) : &$input; + convert_to_string(p); + temp.assign(Z_STRVAL_P(p), Z_STRLEN_P(p)); + $1 = &temp; + } %} %typemap(directorout) string & ($*1_ltype *temp) %{ - convert_to_string_ex(&$input); + if (!EG(exception)) { + convert_to_string($input); temp = new $*1_ltype(Z_STRVAL_P($input), Z_STRLEN_P($input)); swig_acquire_ownership(temp); $result = temp; + } %} %typemap(argout) string & %{ - ZVAL_STRINGL(*($input), const_cast($1->data()), $1->size(), 1); + if (Z_ISREF($input)) { + ZVAL_STRINGL(Z_REFVAL($input), $1->data(), $1->size()); + } %} /* SWIG will apply the non-const typemap above to const string& without diff --git a/Lib/php/std_vector.i b/Lib/php/std_vector.i index 9cc1486ef..e633bc3ad 100644 --- a/Lib/php/std_vector.i +++ b/Lib/php/std_vector.i @@ -14,10 +14,17 @@ namespace std { template class vector { public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef const value_type& const_reference; + vector(); vector(size_type n); + vector(const vector& other); + size_type size() const; size_type capacity() const; void reserve(size_type n); @@ -56,10 +63,17 @@ namespace std { template<> class vector { public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef bool value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; typedef bool const_reference; + vector(); vector(size_type n); + vector(const vector& other); + size_type size() const; size_type capacity() const; void reserve(size_type n); diff --git a/Lib/php/stl.i b/Lib/php/stl.i index 9d2e91eee..04f86014f 100644 --- a/Lib/php/stl.i +++ b/Lib/php/stl.i @@ -1,7 +1,5 @@ /* ----------------------------------------------------------------------------- * stl.i - * - * Initial STL definition. extended as needed in each language * ----------------------------------------------------------------------------- */ %include diff --git a/Lib/php/typemaps.i b/Lib/php/typemaps.i index faae0a6ac..c248a588e 100644 --- a/Lib/php/typemaps.i +++ b/Lib/php/typemaps.i @@ -27,87 +27,77 @@ %define BOOL_TYPEMAP(TYPE) %typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) %{ - convert_to_boolean_ex($input); - temp = Z_LVAL_PP($input) ? true : false; + convert_to_boolean(&$input); + temp = (Z_TYPE($input) == IS_TRUE); $1 = &temp; %} %typemap(argout) TYPE *INPUT, TYPE &INPUT ""; %typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT { - zval *o; - MAKE_STD_ZVAL(o); - ZVAL_BOOL(o,temp$argnum); - t_output_helper( &$result, o TSRMLS_CC ); + zval o; + ZVAL_BOOL(&o, temp$argnum); + t_output_helper($result, &o); } %typemap(in) TYPE *REFERENCE (TYPE lvalue), TYPE &REFERENCE (TYPE lvalue) %{ - convert_to_boolean_ex($input); - lvalue = (*$input)->value.lval ? true : false; + convert_to_boolean($input); + lvalue = (Z_TYPE_P($input) == IS_TRUE); $1 = &lvalue; %} %typemap(argout) TYPE *REFERENCE, TYPE &REFERENCE %{ - (*$arg)->value.lval = lvalue$argnum ? true : false; - (*$arg)->type = IS_BOOL; + ZVAL_BOOL(&$arg, lvalue$argnum ? true : false); %} %enddef %define DOUBLE_TYPEMAP(TYPE) %typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) %{ - convert_to_double_ex($input); - temp = (TYPE) Z_DVAL_PP($input); + temp = (TYPE) zval_get_double(&$input); $1 = &temp; %} %typemap(argout) TYPE *INPUT, TYPE &INPUT ""; %typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT { - zval *o; - MAKE_STD_ZVAL(o); - ZVAL_DOUBLE(o,temp$argnum); - t_output_helper( &$result, o TSRMLS_CC ); + zval o; + ZVAL_DOUBLE(&o, temp$argnum); + t_output_helper($result, &o); } %typemap(in) TYPE *REFERENCE (TYPE dvalue), TYPE &REFERENCE (TYPE dvalue) %{ - convert_to_double_ex($input); - dvalue = (TYPE) (*$input)->value.dval; + dvalue = (TYPE) zval_get_double(&$input); $1 = &dvalue; %} %typemap(argout) TYPE *REFERENCE, TYPE &REFERENCE %{ - $1->value.dval = (double)(lvalue$argnum); - $1->type = IS_DOUBLE; + ZVAL_DOUBLE(&$arg, (double)(lvalue$argnum)); %} %enddef %define INT_TYPEMAP(TYPE) %typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) %{ - convert_to_long_ex($input); - temp = (TYPE) Z_LVAL_PP($input); + temp = (TYPE) zval_get_long(&$input); $1 = &temp; %} %typemap(argout) TYPE *INPUT, TYPE &INPUT ""; %typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT { - zval *o; - MAKE_STD_ZVAL(o); - ZVAL_LONG(o,temp$argnum); - t_output_helper( &$result, o TSRMLS_CC ); + zval o; + ZVAL_LONG(&o, temp$argnum); + t_output_helper($result, &o); } %typemap(in) TYPE *REFERENCE (TYPE lvalue), TYPE &REFERENCE (TYPE lvalue) %{ - convert_to_long_ex($input); - lvalue = (TYPE) (*$input)->value.lval; + lvalue = (TYPE) zval_get_long(&$input); $1 = &lvalue; %} %typemap(argout) TYPE *REFERENCE, TYPE &REFERENCE %{ - (*$arg)->value.lval = (long)(lvalue$argnum); - (*$arg)->type = IS_LONG; + ZVAL_LONG(&$arg, (long)(lvalue$argnum)); %} %enddef @@ -128,16 +118,15 @@ INT_TYPEMAP(signed char); INT_TYPEMAP(long long); %typemap(argout,fragment="t_output_helper") long long *OUTPUT { - zval *o; - MAKE_STD_ZVAL(o); + zval o; if ((long long)LONG_MIN <= temp$argnum && temp$argnum <= (long long)LONG_MAX) { - ZVAL_LONG(o, temp$argnum); + ZVAL_LONG(&o, (long)temp$argnum); } else { char temp[256]; sprintf(temp, "%lld", (long long)temp$argnum); - ZVAL_STRING(o, temp, 1); + ZVAL_STRING(&o, temp); } - t_output_helper( &$result, o TSRMLS_CC ); + t_output_helper($result, &o); } %typemap(in) TYPE *REFERENCE (long long lvalue) %{ @@ -147,38 +136,35 @@ INT_TYPEMAP(long long); %typemap(argout) long long *REFERENCE %{ if ((long long)LONG_MIN <= lvalue$argnum && lvalue$argnum <= (long long)LONG_MAX) { - (*$arg)->value.lval = (long)(lvalue$argnum); - (*$arg)->type = IS_LONG; + ZVAL_LONG(&$arg, (long)temp$argnum); } else { char temp[256]; sprintf(temp, "%lld", (long long)lvalue$argnum); - ZVAL_STRING((*$arg), temp, 1); + ZVAL_STRING(&$arg, temp); } %} %typemap(argout) long long &OUTPUT %{ if ((long long)LONG_MIN <= *arg$argnum && *arg$argnum <= (long long)LONG_MAX) { - ($result)->value.lval = (long)(*arg$argnum); - ($result)->type = IS_LONG; + ZVAL_LONG($result, (long)(*arg$argnum)); } else { char temp[256]; sprintf(temp, "%lld", (long long)(*arg$argnum)); - ZVAL_STRING($result, temp, 1); + ZVAL_STRING($result, temp); } %} INT_TYPEMAP(unsigned long long); %typemap(argout,fragment="t_output_helper") unsigned long long *OUTPUT { - zval *o; - MAKE_STD_ZVAL(o); + zval o; if (temp$argnum <= (unsigned long long)LONG_MAX) { - ZVAL_LONG(o, temp$argnum); + ZVAL_LONG(&o, temp$argnum); } else { char temp[256]; sprintf(temp, "%llu", (unsigned long long)temp$argnum); - ZVAL_STRING(o, temp, 1); + ZVAL_STRING(&o, temp); } - t_output_helper( &$result, o TSRMLS_CC ); + t_output_helper($result, &o); } %typemap(in) TYPE *REFERENCE (unsigned long long lvalue) %{ @@ -188,23 +174,21 @@ INT_TYPEMAP(unsigned long long); %typemap(argout) unsigned long long *REFERENCE %{ if (lvalue$argnum <= (unsigned long long)LONG_MAX) { - (*$arg)->value.lval = (long)(lvalue$argnum); - (*$arg)->type = IS_LONG; + ZVAL_LONG($arg, (long)(lvalue$argnum)); } else { char temp[256]; sprintf(temp, "%llu", (unsigned long long)lvalue$argnum); - ZVAL_STRING((*$arg), temp, 1); + ZVAL_STRING((*$arg), temp); } %} %typemap(argout) unsigned long long &OUTPUT %{ if (*arg$argnum <= (unsigned long long)LONG_MAX) { - ($result)->value.lval = (long)(*arg$argnum); - ($result)->type = IS_LONG; + ZVAL_LONG($result, (long)(*arg$argnum)); } else { char temp[256]; sprintf(temp, "%llu", (unsigned long long)(*arg$argnum)); - ZVAL_STRING($result, temp, 1); + ZVAL_STRING($result, temp); } %} @@ -270,18 +254,17 @@ INT_TYPEMAP(unsigned long long); %typemap(in) char INPUT[ANY] ( char temp[$1_dim0] ) %{ - convert_to_string_ex($input); - strncpy(temp,Z_STRVAL_PP($input),$1_dim0); + convert_to_string(&$input); + strncpy(temp, Z_STRVAL($input), $1_dim0); $1 = temp; %} %typemap(in,numinputs=0) char OUTPUT[ANY] ( char temp[$1_dim0] ) "$1 = temp;"; %typemap(argout,fragment="t_output_helper") char OUTPUT[ANY] { - zval *o; - MAKE_STD_ZVAL(o); - ZVAL_STRINGL(o,temp$argnum,$1_dim0); - t_output_helper( &$result, o TSRMLS_CC ); + zval o; + ZVAL_STRINGL(&o, temp$argnum, $1_dim0); + t_output_helper($result, &o); } %typemap(in,numinputs=0) void **OUTPUT (int force), @@ -289,9 +272,9 @@ INT_TYPEMAP(unsigned long long); %{ /* If they pass NULL by reference, make it into a void* This bit should go in arginit if arginit support init-ing scripting args */ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0) { + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0) { /* So... we didn't get a ref or ptr, but we'll accept NULL by reference */ - if (!((*$input)->type==IS_NULL && PZVAL_IS_REF(*$input))) { + if (!(Z_ISREF($input) && Z_ISNULL_P(Z_REFVAL($input)))) { /* wasn't a pre/ref/thing, OR anything like an int thing */ SWIG_PHP_Error(E_ERROR, "Type error in argument $arg of $symname."); } @@ -313,7 +296,7 @@ INT_TYPEMAP(unsigned long long); void *&OUTPUT %{ if (force$argnum) { /* pass back arg$argnum through params ($arg) if we can */ - if (!PZVAL_IS_REF(*$arg)) { + if (!Z_ISREF($arg)) { SWIG_PHP_Error(E_WARNING, "Parameter $argnum of $symname wasn't passed by reference"); } else { SWIG_SetPointerZval(*$arg, (void *) ptr$argnum, $*1_descriptor, 1); diff --git a/Lib/php/utils.i b/Lib/php/utils.i index 408a3b366..ed6e08ff4 100644 --- a/Lib/php/utils.i +++ b/Lib/php/utils.i @@ -1,70 +1,65 @@ %define CONVERT_BOOL_IN(lvar,t,invar) - convert_to_boolean_ex(invar); - lvar = (t) Z_LVAL_PP(invar); + lvar = (t) zval_is_true(&invar); %enddef %define CONVERT_INT_IN(lvar,t,invar) - convert_to_long_ex(invar); - lvar = (t) Z_LVAL_PP(invar); + lvar = (t) zval_get_long(&invar); %enddef %define CONVERT_LONG_LONG_IN(lvar,t,invar) - switch ((*(invar))->type) { + switch (Z_TYPE(invar)) { case IS_DOUBLE: - lvar = (t) (*(invar))->value.dval; + lvar = (t) Z_DVAL(invar); break; case IS_STRING: { char * endptr; errno = 0; - lvar = (t) strtoll((*(invar))->value.str.val, &endptr, 10); + lvar = (t) strtoll(Z_STRVAL(invar), &endptr, 10); if (*endptr && !errno) break; /* FALL THRU */ } default: - convert_to_long_ex(invar); - lvar = (t) (*(invar))->value.lval; + lvar = (t) zval_get_long(&invar); } %enddef %define CONVERT_UNSIGNED_LONG_LONG_IN(lvar,t,invar) - switch ((*(invar))->type) { + switch (Z_TYPE(invar)) { case IS_DOUBLE: - lvar = (t) (*(invar))->value.dval; + lvar = (t) Z_DVAL(invar); break; case IS_STRING: { char * endptr; errno = 0; - lvar = (t) strtoull((*(invar))->value.str.val, &endptr, 10); + lvar = (t) strtoull(Z_STRVAL(invar), &endptr, 10); if (*endptr && !errno) break; /* FALL THRU */ } default: - convert_to_long_ex(invar); - lvar = (t) (*(invar))->value.lval; + lvar = (t) zval_get_long(&invar); } %enddef %define CONVERT_INT_OUT(lvar,invar) - lvar = (t) Z_LVAL_PP(invar); + lvar = (t) zval_get_long(&invar); %enddef %define CONVERT_FLOAT_IN(lvar,t,invar) - convert_to_double_ex(invar); - lvar = (t) Z_DVAL_PP(invar); + lvar = (t) zval_get_double(&invar); %enddef %define CONVERT_CHAR_IN(lvar,t,invar) - convert_to_string_ex(invar); - lvar = (t) *Z_STRVAL_PP(invar); + convert_to_string(&invar); + lvar = (t) Z_STRVAL(invar)[0]; %enddef %define CONVERT_STRING_IN(lvar,t,invar) - if ((*invar)->type==IS_NULL) { + if (Z_ISNULL(invar)) { lvar = (t) 0; } else { - convert_to_string_ex(invar); - lvar = (t) Z_STRVAL_PP(invar); + convert_to_string(&invar); + lvar = (t) Z_STRVAL(invar); } %enddef @@ -80,35 +75,36 @@ %} %typemap(directorout) TYPE %{ - CONVERT_IN($result,$1_ltype,&$input); + if (!EG(exception)) { + CONVERT_IN($result, $1_ltype, *$input); + } %} %typemap(directorout) const TYPE & ($*1_ltype temp) %{ - CONVERT_IN(temp,$*1_ltype,&$input); + if (!EG(exception)) { + CONVERT_IN(temp, $*1_ltype, *$input); + } $result = &temp; %} %enddef %fragment("t_output_helper","header") %{ static void -t_output_helper(zval **target, zval *o TSRMLS_DC) { - zval *tmp; - if ( (*target)->type == IS_ARRAY ) { +t_output_helper(zval *target, zval *o) { + zval tmp; + if (Z_TYPE_P(target) == IS_ARRAY) { /* it's already an array, just append */ - add_next_index_zval( *target, o ); + add_next_index_zval(target, o); return; } - if ( (*target)->type == IS_NULL ) { - REPLACE_ZVAL_VALUE(target,o,1); - FREE_ZVAL(o); + if (Z_TYPE_P(target) == IS_NULL) { + /* NULL isn't refcounted */ + ZVAL_COPY_VALUE(target, o); return; } - ALLOC_INIT_ZVAL(tmp); - *tmp = **target; - zval_copy_ctor(tmp); - array_init(*target); - add_next_index_zval( *target, tmp); - add_next_index_zval( *target, o); - + ZVAL_DUP(&tmp, target); + array_init(target); + add_next_index_zval(target, &tmp); + add_next_index_zval(target, o); } %} diff --git a/Lib/pike/pike.swg b/Lib/pike/pike.swg index 95cc20835..a36bf3ad2 100644 --- a/Lib/pike/pike.swg +++ b/Lib/pike/pike.swg @@ -273,6 +273,8 @@ extern "C" { /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } /* ------------------------------------------------------------ * Overloaded operator support diff --git a/Lib/python/boost_shared_ptr.i b/Lib/python/boost_shared_ptr.i index 40a1ae1ef..709e7811d 100644 --- a/Lib/python/boost_shared_ptr.i +++ b/Lib/python/boost_shared_ptr.i @@ -18,7 +18,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor wrapper customisation -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -29,7 +29,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); @@ -62,13 +62,31 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) { + int newmem = 0; + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res, "$type"); + } + if (!swig_argp) { + %dirout_nullref("$type"); + } else { + $result = *(%reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get()); + if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); + } +} + // plain pointer // Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance %typemap(in) CONST TYPE * (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -108,12 +126,20 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter_python") CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE * %{ +#error "directorout typemap for plain pointer not implemented" +%} + // plain reference %typemap(in) CONST TYPE & (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { @@ -153,13 +179,21 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter_python") CONST TYPE & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(&$1 SWIG_NO_NULL_DELETER_0); + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE & %{ +#error "directorout typemap for plain reference not implemented" +%} + // plain pointer by reference // Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance %typemap(in) TYPE *CONST& (void *argp = 0, int res = 0, $*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -171,7 +205,7 @@ $1 = &temp; } %typemap(out, fragment="SWIG_null_deleter_python") TYPE *CONST& { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -182,12 +216,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter_python") TYPE *CONST& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) TYPE *CONST& %{ +#error "directorout typemap for plain pointer by reference not implemented" +%} + // shared_ptr by value %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *argp, int res = 0) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) $1 = *(%reinterpret_cast(argp, $<ype)); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $<ype); @@ -212,12 +254,28 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *swig_argp, int swig_res = 0) { + int newmem = 0; + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res, "$type"); + } + if (swig_argp) { + $result = *(%reinterpret_cast(swig_argp, $<ype)); + if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, $<ype); + } +} + // shared_ptr by reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (void *argp, int res = 0, $*1_ltype tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -239,12 +297,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{ +#error "directorout typemap for shared_ptr ref not implemented" +%} + // shared_ptr by pointer %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (void *argp, int res = 0, $*1_ltype tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -255,7 +321,7 @@ } } %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 && *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); if ($owner) delete $1; } @@ -267,12 +333,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{ +#error "directorout typemap for pointer to shared_ptr not implemented" +%} + // shared_ptr by pointer reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (void *argp, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, $*1_ltype temp = 0) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) tempshared = *%reinterpret_cast(argp, $*ltype); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $*ltype); @@ -280,7 +354,7 @@ $1 = &temp; } %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 && **$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -291,10 +365,18 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{ +#error "directorout typemap for pointer ref to shared_ptr not implemented" +%} + // Typecheck typemaps -// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting +// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, @@ -316,9 +398,14 @@ #error "typemaps for $1_type not available" %} +%typemap(doctype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + %{TYPE%} + %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef - diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg index 1244dbbcc..28051e67b 100644 --- a/Lib/python/builtin.swg +++ b/Lib/python/builtin.swg @@ -1,220 +1,31 @@ -#define SWIGPY_UNARYFUNC_CLOSURE(wrapper) \ -SWIGINTERN PyObject * \ -wrapper##_closure(PyObject *a) { \ - return wrapper(a, NULL); \ -} - -#define SWIGPY_DESTRUCTOR_CLOSURE(wrapper) \ -SWIGINTERN void \ -wrapper##_closure(PyObject *a) { \ - SwigPyObject *sobj; \ - sobj = (SwigPyObject *)a; \ - Py_XDECREF(sobj->dict); \ - if (sobj->own) { \ - PyObject *o; \ - PyObject *val = 0, *type = 0, *tb = 0; \ - PyErr_Fetch(&val, &type, &tb); \ - o = wrapper(a, NULL); \ - if (!o) { \ - PyObject *deallocname = PyString_FromString(#wrapper); \ - PyErr_WriteUnraisable(deallocname); \ - Py_DECREF(deallocname); \ - } \ - PyErr_Restore(val, type, tb); \ - Py_XDECREF(o); \ - } \ - if (PyType_IS_GC(a->ob_type)) { \ - PyObject_GC_Del(a); \ - } else { \ - PyObject_Del(a); \ - } \ -} - -#define SWIGPY_INQUIRY_CLOSURE(wrapper) \ -SWIGINTERN int \ -wrapper##_closure(PyObject *a) { \ - PyObject *pyresult; \ - int result; \ - pyresult = wrapper(a, NULL); \ - result = pyresult && PyObject_IsTrue(pyresult) ? 1 : 0; \ - Py_XDECREF(pyresult); \ - return result; \ -} - -#define SWIGPY_BINARYFUNC_CLOSURE(wrapper) \ -SWIGINTERN PyObject * \ -wrapper##_closure(PyObject *a, PyObject *b) { \ - PyObject *tuple, *result; \ - tuple = PyTuple_New(1); \ - assert(tuple); \ - PyTuple_SET_ITEM(tuple, 0, b); \ - Py_XINCREF(b); \ - result = wrapper(a, tuple); \ - Py_DECREF(tuple); \ - return result; \ -} - -typedef ternaryfunc ternarycallfunc; - -#define SWIGPY_TERNARYFUNC_CLOSURE(wrapper) \ -SWIGINTERN PyObject * \ -wrapper##_closure(PyObject *a, PyObject *b, PyObject *c) { \ - PyObject *tuple, *result; \ - tuple = PyTuple_New(2); \ - assert(tuple); \ - PyTuple_SET_ITEM(tuple, 0, b); \ - PyTuple_SET_ITEM(tuple, 1, c); \ - Py_XINCREF(b); \ - Py_XINCREF(c); \ - result = wrapper(a, tuple); \ - Py_DECREF(tuple); \ - return result; \ -} - -#define SWIGPY_TERNARYCALLFUNC_CLOSURE(wrapper) \ -SWIGINTERN PyObject * \ -wrapper##_closure(PyObject *callable_object, PyObject *args, PyObject *) { \ - return wrapper(callable_object, args); \ -} - -#define SWIGPY_LENFUNC_CLOSURE(wrapper) \ -SWIGINTERN Py_ssize_t \ -wrapper##_closure(PyObject *a) { \ - PyObject *resultobj; \ - Py_ssize_t result; \ - resultobj = wrapper(a, NULL); \ - result = PyNumber_AsSsize_t(resultobj, NULL); \ - Py_DECREF(resultobj); \ - return result; \ -} - -#define SWIGPY_SSIZESSIZEARGFUNC_CLOSURE(wrapper) \ -SWIGINTERN PyObject * \ -wrapper##_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c) { \ - PyObject *tuple, *result; \ - tuple = PyTuple_New(2); \ - assert(tuple); \ - PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ - PyTuple_SET_ITEM(tuple, 1, _PyLong_FromSsize_t(c)); \ - result = wrapper(a, tuple); \ - Py_DECREF(tuple); \ - return result; \ -} - -#define SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE(wrapper) \ -SWIGINTERN int \ -wrapper##_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c, PyObject *d) { \ - PyObject *tuple, *resultobj; \ - int result; \ - tuple = PyTuple_New(d ? 3 : 2); \ - assert(tuple); \ - PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ - PyTuple_SET_ITEM(tuple, 1, _PyLong_FromSsize_t(c)); \ - if (d) { \ - PyTuple_SET_ITEM(tuple, 2, d); \ - Py_INCREF(d); \ - } \ - resultobj = wrapper(a, tuple); \ - result = resultobj ? 0 : -1; \ - Py_DECREF(tuple); \ - Py_XDECREF(resultobj); \ - return result; \ -} - -#define SWIGPY_SSIZEARGFUNC_CLOSURE(wrapper) \ -SWIGINTERN PyObject * \ -wrapper##_closure(PyObject *a, Py_ssize_t b) { \ - PyObject *tuple, *result; \ - tuple = PyTuple_New(1); \ - assert(tuple); \ - PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ - result = wrapper(a, tuple); \ - Py_DECREF(tuple); \ - return result; \ -} - -#define SWIGPY_FUNPACK_SSIZEARGFUNC_CLOSURE(wrapper) \ -SWIGINTERN PyObject * \ -wrapper##_closure(PyObject *a, Py_ssize_t b) { \ - PyObject *arg, *result; \ - arg = _PyLong_FromSsize_t(b); \ - result = wrapper(a, arg); \ - Py_DECREF(arg); \ - return result; \ -} - -#define SWIGPY_SSIZEOBJARGPROC_CLOSURE(wrapper) \ -SWIGINTERN int \ -wrapper##_closure(PyObject *a, Py_ssize_t b, PyObject *c) { \ - PyObject *tuple, *resultobj; \ - int result; \ - tuple = PyTuple_New(2); \ - assert(tuple); \ - PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ - PyTuple_SET_ITEM(tuple, 1, c); \ - Py_XINCREF(c); \ - resultobj = wrapper(a, tuple); \ - result = resultobj ? 0 : -1; \ - Py_XDECREF(resultobj); \ - Py_DECREF(tuple); \ - return result; \ -} - -#define SWIGPY_OBJOBJARGPROC_CLOSURE(wrapper) \ -SWIGINTERN int \ -wrapper##_closure(PyObject *a, PyObject *b, PyObject *c) { \ - PyObject *tuple, *resultobj; \ - int result; \ - tuple = PyTuple_New(c ? 2 : 1); \ - assert(tuple); \ - PyTuple_SET_ITEM(tuple, 0, b); \ - Py_XINCREF(b); \ - if (c) { \ - PyTuple_SET_ITEM(tuple, 1, c); \ - Py_XINCREF(c); \ - } \ - resultobj = wrapper(a, tuple); \ - result = resultobj ? 0 : -1; \ - Py_XDECREF(resultobj); \ - Py_DECREF(tuple); \ - return result; \ -} - -#define SWIGPY_REPRFUNC_CLOSURE(wrapper) \ -SWIGINTERN PyObject * \ -wrapper##_closure(PyObject *a) { \ - return wrapper(a, NULL); \ -} - -#define SWIGPY_HASHFUNC_CLOSURE(wrapper) \ -SWIGINTERN Py_hash_t \ -wrapper##_closure(PyObject *a) { \ - PyObject *pyresult; \ - Py_hash_t result; \ - pyresult = wrapper(a, NULL); \ - if (!pyresult) \ - return -1; \ - result = SWIG_PyNumber_AsPyHash(pyresult); \ - Py_DECREF(pyresult); \ - return result; \ -} - -#define SWIGPY_ITERNEXT_CLOSURE(wrapper) \ -SWIGINTERN PyObject * \ -wrapper##_closure(PyObject *a) { \ - PyObject *result; \ - result = wrapper(a, NULL); \ - if (result && result == Py_None) { \ - Py_DECREF(result); \ - result = NULL; \ - } \ - return result; \ -} - #ifdef __cplusplus extern "C" { #endif +SWIGINTERN Py_hash_t +SwigPyObject_hash(PyObject *obj) { + SwigPyObject *sobj = (SwigPyObject *)obj; + void *ptr = sobj->ptr; + return (Py_hash_t)ptr; +} + +SWIGINTERN Py_hash_t +SWIG_PyNumber_AsPyHash(PyObject *obj) { + Py_hash_t result = -1; +#if PY_VERSION_HEX < 0x03020000 + if (PyInt_Check(obj)) + result = PyInt_AsLong(obj); + else if (PyLong_Check(obj)) + result = PyLong_AsLong(obj); +#else + if (PyNumber_Check(obj)) + result = PyNumber_AsSsize_t(obj, NULL); +#endif + else + PyErr_Format(PyExc_TypeError, "Wrong type for hash function"); + return PyErr_Occurred() ? -1 : result; +} + SWIGINTERN int SwigPyBuiltin_BadInit(PyObject *self, PyObject *SWIGUNUSEDPARM(args), PyObject *SWIGUNUSEDPARM(kwds)) { PyErr_Format(PyExc_TypeError, "Cannot create new instances of type '%.300s'", self->ob_type->tp_name); @@ -229,28 +40,6 @@ SwigPyBuiltin_BadDealloc(PyObject *obj) { } } -SWIGINTERN Py_hash_t -SwigPyObject_hash(PyObject *obj) { - SwigPyObject *sobj = (SwigPyObject *)obj; - void *ptr = sobj->ptr; - return (Py_hash_t)ptr; -} - -SWIGINTERN Py_hash_t -SWIG_PyNumber_AsPyHash(PyObject *obj) { - Py_hash_t result = -1; -#if PY_VERSION_HEX < 0x03020000 - if (PyLong_Check(obj)) - result = PyLong_AsLong(obj); -#else - if (PyNumber_Check(obj)) - result = PyNumber_AsSsize_t(obj, NULL); -#endif - else - PyErr_Format(PyExc_TypeError, "Wrong type for hash function"); - return result; -} - typedef struct { PyCFunction get; PyCFunction set; @@ -300,8 +89,8 @@ SwigPyBuiltin_SetterClosure (PyObject *obj, PyObject *val, void *closure) { } tuple = PyTuple_New(1); assert(tuple); + Py_INCREF(val); PyTuple_SET_ITEM(tuple, 0, val); - Py_XINCREF(val); result = (*getset->set)(obj, tuple); Py_DECREF(tuple); Py_XDECREF(result); @@ -328,7 +117,7 @@ SwigPyBuiltin_FunpackSetterClosure (PyObject *obj, PyObject *val, void *closure) SWIGINTERN void SwigPyStaticVar_dealloc(PyDescrObject *descr) { - _PyObject_GC_UNTRACK(descr); + PyObject_GC_UnTrack(descr); Py_XDECREF(PyDescr_TYPE(descr)); Py_XDECREF(PyDescr_NAME(descr)); PyObject_GC_Del(descr); @@ -377,9 +166,13 @@ SwigPyStaticVar_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) } SWIGINTERN int -SwigPyObjectType_setattro(PyTypeObject *type, PyObject *name, PyObject *value) { +SwigPyObjectType_setattro(PyObject *typeobject, PyObject *name, PyObject *value) { PyObject *attribute; + PyTypeObject *type; descrsetfunc local_set; + + assert(PyType_Check(typeobject)); + type = (PyTypeObject *)typeobject; attribute = _PyType_Lookup(type, name); if (attribute != NULL) { /* Implement descriptor functionality, if any */ @@ -458,12 +251,8 @@ SwigPyStaticVar_Type(void) { 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ -#if PY_VERSION_HEX >= 0x02030000 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 0, /* tp_version_tag */ -#endif #if PY_VERSION_HEX >= 0x03040000 0, /* tp_finalize */ #endif @@ -471,24 +260,97 @@ SwigPyStaticVar_Type(void) { 0, /* tp_allocs */ 0, /* tp_frees */ 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 0, /* tp_prev */ -#endif 0 /* tp_next */ #endif }; staticvar_type = tmp; type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - staticvar_type.ob_type = &PyType_Type; -#else if (PyType_Ready(&staticvar_type) < 0) return NULL; -#endif } return &staticvar_type; } +SWIGINTERN PyTypeObject* +SwigPyObjectType(void) { + static char swigpyobjecttype_doc[] = "Metaclass for SWIG wrapped types"; + static PyTypeObject swigpyobjecttype_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp = { +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(&PyType_Type, 0) +#else + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ +#endif + "SwigPyObjectType", /* tp_name */ + PyType_Type.tp_basicsize, /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + SwigPyObjectType_setattro, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_CLASS, /* tp_flags */ + swigpyobjecttype_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ +#if PY_VERSION_HEX >= 0x03040000 + 0, /* tp_finalize */ +#endif +#ifdef COUNT_ALLOCS + 0, /* tp_allocs */ + 0, /* tp_frees */ + 0, /* tp_maxalloc */ + 0, /* tp_prev */ + 0 /* tp_next */ +#endif + }; + swigpyobjecttype_type = tmp; + type_init = 1; + swigpyobjecttype_type.tp_base = &PyType_Type; + if (PyType_Ready(&swigpyobjecttype_type) < 0) + return NULL; + } + return &swigpyobjecttype_type; +} + SWIGINTERN PyGetSetDescrObject * SwigPyStaticVar_new_getset(PyTypeObject *type, PyGetSetDef *getset) { @@ -508,10 +370,10 @@ SwigPyStaticVar_new_getset(PyTypeObject *type, PyGetSetDef *getset) { SWIGINTERN void SwigPyBuiltin_InitBases (PyTypeObject *type, PyTypeObject **bases) { - int base_count = 0; + Py_ssize_t base_count = 0; PyTypeObject **b; PyObject *tuple; - int i; + Py_ssize_t i; if (!bases[0]) { bases[0] = SwigPyObject_type(); @@ -523,8 +385,8 @@ SwigPyBuiltin_InitBases (PyTypeObject *type, PyTypeObject **bases) { ++base_count; tuple = PyTuple_New(base_count); for (i = 0; i < base_count; ++i) { - PyTuple_SET_ITEM(tuple, i, (PyObject *)bases[i]); Py_INCREF((PyObject *)bases[i]); + PyTuple_SET_ITEM(tuple, i, (PyObject *)bases[i]); } type->tp_bases = tuple; } @@ -547,6 +409,331 @@ SwigPyBuiltin_SetMetaType (PyTypeObject *type, PyTypeObject *metatype) #endif } + +/* Start of callback function macros for use in PyTypeObject */ + +typedef PyObject *(*SwigPyWrapperFunction)(PyObject *, PyObject *); + +#define SWIGPY_UNARYFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_unaryfunc_closure(PyObject *a) { \ + return SwigPyBuiltin_unaryfunc_closure(wrapper, a); \ +} +SWIGINTERN PyObject * +SwigPyBuiltin_unaryfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) { + return wrapper(a, NULL); +} + +#define SWIGPY_DESTRUCTOR_CLOSURE(wrapper) \ +SWIGINTERN void \ +wrapper##_destructor_closure(PyObject *a) { \ + SwigPyBuiltin_destructor_closure(wrapper, #wrapper, a); \ +} +SWIGINTERN void +SwigPyBuiltin_destructor_closure(SwigPyWrapperFunction wrapper, const char *wrappername, PyObject *a) { + SwigPyObject *sobj; + sobj = (SwigPyObject *)a; + Py_XDECREF(sobj->dict); + if (sobj->own) { + PyObject *o; + PyObject *type = 0, *value = 0, *traceback = 0; + PyErr_Fetch(&type, &value, &traceback); + o = wrapper(a, NULL); + if (!o) { + PyObject *deallocname = PyString_FromString(wrappername); + PyErr_WriteUnraisable(deallocname); + Py_DECREF(deallocname); + } + PyErr_Restore(type, value, traceback); + Py_XDECREF(o); + } + if (PyType_IS_GC(a->ob_type)) { + PyObject_GC_Del(a); + } else { + PyObject_Del(a); + } +} + +#define SWIGPY_INQUIRY_CLOSURE(wrapper) \ +SWIGINTERN int \ +wrapper##_inquiry_closure(PyObject *a) { \ + return SwigPyBuiltin_inquiry_closure(wrapper, a); \ +} +SWIGINTERN int +SwigPyBuiltin_inquiry_closure(SwigPyWrapperFunction wrapper, PyObject *a) { + PyObject *pyresult; + int result; + pyresult = wrapper(a, NULL); + result = pyresult && PyObject_IsTrue(pyresult) ? 1 : 0; + Py_XDECREF(pyresult); + return result; +} + +#define SWIGPY_GETITERFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_getiterfunc_closure(PyObject *a) { \ + return SwigPyBuiltin_getiterfunc_closure(wrapper, a); \ +} +SWIGINTERN PyObject * +SwigPyBuiltin_getiterfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) { + return wrapper(a, NULL); +} + +#define SWIGPY_BINARYFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_binaryfunc_closure(PyObject *a, PyObject *b) { \ + return SwigPyBuiltin_binaryfunc_closure(wrapper, a, b); \ +} +SWIGINTERN PyObject * +SwigPyBuiltin_binaryfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b) { + PyObject *tuple, *result; + tuple = PyTuple_New(1); + assert(tuple); + Py_INCREF(b); + PyTuple_SET_ITEM(tuple, 0, b); + result = wrapper(a, tuple); + Py_DECREF(tuple); + return result; +} + +typedef ternaryfunc ternarycallfunc; + +#define SWIGPY_TERNARYFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_ternaryfunc_closure(PyObject *a, PyObject *b, PyObject *c) { \ + return SwigPyBuiltin_ternaryfunc_closure(wrapper, a, b, c); \ +} +SWIGINTERN PyObject * +SwigPyBuiltin_ternaryfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b, PyObject *c) { + PyObject *tuple, *result; + tuple = PyTuple_New(2); + assert(tuple); + Py_INCREF(b); + PyTuple_SET_ITEM(tuple, 0, b); + Py_INCREF(c); + PyTuple_SET_ITEM(tuple, 1, c); + result = wrapper(a, tuple); + Py_DECREF(tuple); + return result; +} + +#define SWIGPY_TERNARYCALLFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_ternarycallfunc_closure(PyObject *a, PyObject *b, PyObject *c) { \ + return SwigPyBuiltin_ternarycallfunc_closure(wrapper, a, b, c); \ +} +SWIGINTERN PyObject * +SwigPyBuiltin_ternarycallfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b, PyObject *c) { + (void) c; + return wrapper(a, b); +} + +#define SWIGPY_LENFUNC_CLOSURE(wrapper) \ +SWIGINTERN Py_ssize_t \ +wrapper##_lenfunc_closure(PyObject *a) { \ + return SwigPyBuiltin_lenfunc_closure(wrapper, a); \ +} +SWIGINTERN Py_ssize_t +SwigPyBuiltin_lenfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) { + PyObject *resultobj; + Py_ssize_t result; + resultobj = wrapper(a, NULL); + result = PyNumber_AsSsize_t(resultobj, NULL); + Py_DECREF(resultobj); + return result; +} + +#define SWIGPY_SSIZESSIZEARGFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_ssizessizeargfunc_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c) { \ + return SwigPyBuiltin_ssizessizeargfunc_closure(wrapper, a, b, c); \ +} +SWIGINTERN PyObject * +SwigPyBuiltin_ssizessizeargfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, Py_ssize_t b, Py_ssize_t c) { + PyObject *tuple, *result; + tuple = PyTuple_New(2); + assert(tuple); + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); + PyTuple_SET_ITEM(tuple, 1, _PyLong_FromSsize_t(c)); + result = wrapper(a, tuple); + Py_DECREF(tuple); + return result; +} + +#define SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE(wrapper) \ +SWIGINTERN int \ +wrapper##_ssizessizeobjargproc_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c, PyObject *d) { \ + return SwigPyBuiltin_ssizessizeobjargproc_closure(wrapper, a, b, c, d); \ +} +SWIGINTERN int +SwigPyBuiltin_ssizessizeobjargproc_closure(SwigPyWrapperFunction wrapper, PyObject *a, Py_ssize_t b, Py_ssize_t c, PyObject *d) { + PyObject *tuple, *resultobj; + int result; + tuple = PyTuple_New(d ? 3 : 2); + assert(tuple); + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); + PyTuple_SET_ITEM(tuple, 1, _PyLong_FromSsize_t(c)); + if (d) { + Py_INCREF(d); + PyTuple_SET_ITEM(tuple, 2, d); + } + resultobj = wrapper(a, tuple); + result = resultobj ? 0 : -1; + Py_DECREF(tuple); + Py_XDECREF(resultobj); + return result; +} + +#define SWIGPY_SSIZEARGFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_ssizeargfunc_closure(PyObject *a, Py_ssize_t b) { \ + return SwigPyBuiltin_funpack_ssizeargfunc_closure(wrapper, a, b); \ +} +SWIGINTERN PyObject * +SwigPyBuiltin_funpack_ssizeargfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, Py_ssize_t b) { + PyObject *tuple, *result; + tuple = PyTuple_New(1); + assert(tuple); + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); + result = wrapper(a, tuple); + Py_DECREF(tuple); + return result; +} + +#define SWIGPY_FUNPACK_SSIZEARGFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_ssizeargfunc_closure(PyObject *a, Py_ssize_t b) { \ + return SwigPyBuiltin_ssizeargfunc_closure(wrapper, a, b); \ +} +SWIGINTERN PyObject * +SwigPyBuiltin_ssizeargfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, Py_ssize_t b) { + PyObject *arg, *result; + arg = _PyLong_FromSsize_t(b); + result = wrapper(a, arg); + Py_DECREF(arg); + return result; +} + +#define SWIGPY_SSIZEOBJARGPROC_CLOSURE(wrapper) \ +SWIGINTERN int \ +wrapper##_ssizeobjargproc_closure(PyObject *a, Py_ssize_t b, PyObject *c) { \ + return SwigPyBuiltin_ssizeobjargproc_closure(wrapper, a, b, c); \ +} +SWIGINTERN int +SwigPyBuiltin_ssizeobjargproc_closure(SwigPyWrapperFunction wrapper, PyObject *a, Py_ssize_t b, PyObject *c) { + PyObject *tuple, *resultobj; + int result; + tuple = PyTuple_New(2); + assert(tuple); + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); + Py_INCREF(c); + PyTuple_SET_ITEM(tuple, 1, c); + resultobj = wrapper(a, tuple); + result = resultobj ? 0 : -1; + Py_XDECREF(resultobj); + Py_DECREF(tuple); + return result; +} + +#define SWIGPY_OBJOBJPROC_CLOSURE(wrapper) \ +SWIGINTERN int \ +wrapper##_objobjproc_closure(PyObject *a, PyObject *b) { \ + return SwigPyBuiltin_objobjproc_closure(wrapper, a, b); \ +} +SWIGINTERN int +SwigPyBuiltin_objobjproc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b) { + int result; + PyObject *pyresult; + PyObject *tuple; + tuple = PyTuple_New(1); + assert(tuple); + Py_INCREF(b); + PyTuple_SET_ITEM(tuple, 0, b); + pyresult = wrapper(a, tuple); + result = pyresult ? (PyObject_IsTrue(pyresult) ? 1 : 0) : -1; + Py_XDECREF(pyresult); + Py_DECREF(tuple); + return result; +} + +#define SWIGPY_FUNPACK_OBJOBJPROC_CLOSURE(wrapper) \ +SWIGINTERN int \ +wrapper##_objobjproc_closure(PyObject *a, PyObject *b) { \ + return SwigPyBuiltin_funpack_objobjproc_closure(wrapper, a, b); \ +} +SWIGINTERN int +SwigPyBuiltin_funpack_objobjproc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b) { + int result; + PyObject *pyresult; + pyresult = wrapper(a, b); + result = pyresult ? (PyObject_IsTrue(pyresult) ? 1 : 0) : -1; + Py_XDECREF(pyresult); + return result; +} + +#define SWIGPY_OBJOBJARGPROC_CLOSURE(wrapper) \ +SWIGINTERN int \ +wrapper##_objobjargproc_closure(PyObject *a, PyObject *b, PyObject *c) { \ + return SwigPyBuiltin_objobjargproc_closure(wrapper, a, b, c); \ +} +SWIGINTERN int +SwigPyBuiltin_objobjargproc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b, PyObject *c) { + PyObject *tuple, *resultobj; + int result; + tuple = PyTuple_New(c ? 2 : 1); + assert(tuple); + Py_INCREF(b); + PyTuple_SET_ITEM(tuple, 0, b); + if (c) { + Py_INCREF(c); + PyTuple_SET_ITEM(tuple, 1, c); + } + resultobj = wrapper(a, tuple); + result = resultobj ? 0 : -1; + Py_XDECREF(resultobj); + Py_DECREF(tuple); + return result; +} + +#define SWIGPY_REPRFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_reprfunc_closure(PyObject *a) { \ + return SwigPyBuiltin_reprfunc_closure(wrapper, a); \ +} +SWIGINTERN PyObject * +SwigPyBuiltin_reprfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) { + return wrapper(a, NULL); +} + +#define SWIGPY_HASHFUNC_CLOSURE(wrapper) \ +SWIGINTERN Py_hash_t \ +wrapper##_hashfunc_closure(PyObject *a) { \ + return SwigPyBuiltin_hashfunc_closure(wrapper, a); \ +} +SWIGINTERN Py_hash_t +SwigPyBuiltin_hashfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) { + PyObject *pyresult; + Py_hash_t result; + pyresult = wrapper(a, NULL); + if (!pyresult) + return -1; + result = SWIG_PyNumber_AsPyHash(pyresult); + Py_DECREF(pyresult); + return result; +} + +#define SWIGPY_ITERNEXTFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_iternextfunc_closure(PyObject *a) { \ + return SwigPyBuiltin_iternextfunc_closure(wrapper, a);\ +} +SWIGINTERN PyObject * +SwigPyBuiltin_iternextfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) { + return wrapper(a, NULL); +} + +/* End of callback function macros for use in PyTypeObject */ + #ifdef __cplusplus } #endif diff --git a/Lib/python/carrays.i b/Lib/python/carrays.i index e578c80dc..74b2be9c4 100644 --- a/Lib/python/carrays.i +++ b/Lib/python/carrays.i @@ -2,48 +2,8 @@ #if defined(SWIGPYTHON_BUILTIN) %feature("python:slot", "sq_item", functype="ssizeargfunc") NAME::__getitem__; %feature("python:slot", "sq_ass_item", functype="ssizeobjargproc") NAME::__setitem__; - -%inline %{ -typedef struct { - TYPE *el; -} NAME; -%} - -%extend NAME { - - NAME(size_t nelements) { - NAME *arr = %new_instance(NAME); - arr->el = %new_array(nelements, TYPE); - return arr; - } - - ~NAME() { - %delete_array(self->el); - %delete(self); - } - - TYPE __getitem__(size_t index) { - return self->el[index]; - } - - void __setitem__(size_t index, TYPE value) { - self->el[index] = value; - } - - TYPE * cast() { - return self->el; - } - - static NAME *frompointer(TYPE *t) { - return %reinterpret_cast(t, NAME *); - } -}; - -%types(NAME = TYPE); - -#else - %array_class_wrap(TYPE,NAME,__getitem__,__setitem__) #endif +%array_class_wrap(TYPE,NAME,__getitem__,__setitem__) %enddef %include diff --git a/Lib/python/cni.i b/Lib/python/cni.i deleted file mode 100644 index 10a1403a2..000000000 --- a/Lib/python/cni.i +++ /dev/null @@ -1,2 +0,0 @@ -%include -%include diff --git a/Lib/python/defarg.swg b/Lib/python/defarg.swg index 10c991615..59450bd82 100644 --- a/Lib/python/defarg.swg +++ b/Lib/python/defarg.swg @@ -24,7 +24,7 @@ SWIGINTERN PyObject *swig_call_defargs(PyObject *self, PyObject *args) { PyObject *func; PyObject *parms; - if (!PyArg_ParseTuple(args,"OO",&func,&parms)) + if (!PyArg_ParseTuple(args, "OO", &func, &parms)) return NULL; if (!PyCallable_Check(func)) { diff --git a/Lib/python/director.swg b/Lib/python/director.swg index 4bdc94dc2..9694c6233 100644 --- a/Lib/python/director.swg +++ b/Lib/python/director.swg @@ -199,46 +199,6 @@ namespace Swig { } }; - /* unknown exception handler */ - class UnknownExceptionHandler { -#ifdef SWIG_DIRECTOR_UEH - static void handler() { - try { - throw; - } catch (DirectorException& e) { - std::cerr << "SWIG Director exception caught:" << std::endl - << e.what() << std::endl; - } catch (std::exception& e) { - std::cerr << "std::exception caught: "<< e.what() << std::endl; - } catch (...) { - std::cerr << "Unknown exception caught." << std::endl; - } - - std::cerr << std::endl - << "Python interpreter traceback:" << std::endl; - PyErr_Print(); - std::cerr << std::endl; - - std::cerr << "This exception was caught by the SWIG unexpected exception handler." << std::endl - << "Try using %feature(\"director:except\") to avoid reaching this point." << std::endl - << std::endl - << "Exception is being re-thrown, program will likely abort/terminate." << std::endl; - throw; - } - - public: - - std::unexpected_handler old; - UnknownExceptionHandler(std::unexpected_handler nh = handler) { - old = std::set_unexpected(nh); - } - - ~UnknownExceptionHandler() { - std::set_unexpected(old); - } -#endif - }; - /* type mismatch in the return value from a python method call */ class DirectorTypeMismatchException : public DirectorException { public: diff --git a/Lib/python/jstring.i b/Lib/python/jstring.i deleted file mode 100644 index bda95237b..000000000 --- a/Lib/python/jstring.i +++ /dev/null @@ -1,72 +0,0 @@ -%include - -%fragment(SWIG_AsVal_frag(jstring),"header") { -SWIGINTERN int -SWIG_AsVal(jstring)(PyObject *obj, jstring *val) -{ - if (obj == Py_None) { - if (val) *val = 0; - return SWIG_OK; - } - - PyObject *tmp = 0; - int isunicode = PyUnicode_Check(obj); - if (!isunicode && PyString_Check(obj)) { - if (val) { - obj = tmp = PyUnicode_FromObject(obj); - } - isunicode = 1; - } - if (isunicode) { - if (val) { - if (sizeof(Py_UNICODE) == sizeof(jchar)) { - *val = JvNewString((const jchar *) PyUnicode_AS_UNICODE(obj),PyUnicode_GET_SIZE(obj)); - return SWIG_NEWOBJ; - } else { - int len = PyUnicode_GET_SIZE(obj); - Py_UNICODE *pchars = PyUnicode_AS_UNICODE(obj); - *val = JvAllocString (len); - jchar *jchars = JvGetStringChars (*val); - for (int i = 0; i < len; ++i) { - jchars[i] = pchars[i]; - } - return SWIG_NEWOBJ; - } - } - Py_XDECREF(tmp); - return SWIG_OK; - } - return SWIG_TypeError; -} -} - -%fragment(SWIG_From_frag(jstring),"header") { -SWIGINTERNINLINE PyObject * -SWIG_From(jstring)(jstring val) -{ - if (!val) { - return SWIG_Py_Void(); - } - if (sizeof(Py_UNICODE) == sizeof(jchar)) { - return PyUnicode_FromUnicode((const Py_UNICODE *) JvGetStringChars(val), - JvGetStringUTFLength(val)); - } else { - int len = JvGetStringUTFLength(val); - Py_UNICODE pchars[len]; - jchar *jchars = JvGetStringChars(val); - - for (int i = 0; i < len; i++) { - pchars[i] = jchars[i]; - } - return PyUnicode_FromUnicode((const Py_UNICODE *) pchars, len); - } -} -} - -%typemaps_asvalfrom(%checkcode(STRING), - %arg(SWIG_AsVal(jstring)), - %arg(SWIG_From(jstring)), - %arg(SWIG_AsVal_frag(jstring)), - %arg(SWIG_From_frag(jstring)), - java::lang::String *); - diff --git a/Lib/python/pyabc.i b/Lib/python/pyabc.i index 12ce65985..fbd91dce4 100644 --- a/Lib/python/pyabc.i +++ b/Lib/python/pyabc.i @@ -1,10 +1,10 @@ %define %pythonabc(Type, Abc) %feature("python:abc", #Abc) Type; %enddef -%pythoncode %{import collections%} -%pythonabc(std::vector, collections.MutableSequence); -%pythonabc(std::list, collections.MutableSequence); -%pythonabc(std::map, collections.MutableMapping); -%pythonabc(std::multimap, collections.MutableMapping); -%pythonabc(std::set, collections.MutableSet); -%pythonabc(std::multiset, collections.MutableSet); +%pythoncode %{import collections.abc%} +%pythonabc(std::vector, collections.abc.MutableSequence); +%pythonabc(std::list, collections.abc.MutableSequence); +%pythonabc(std::map, collections.abc.MutableMapping); +%pythonabc(std::multimap, collections.abc.MutableMapping); +%pythonabc(std::set, collections.abc.MutableSet); +%pythonabc(std::multiset, collections.abc.MutableSet); diff --git a/Lib/python/pyapi.swg b/Lib/python/pyapi.swg index 2da05f9e9..19e6979b5 100644 --- a/Lib/python/pyapi.swg +++ b/Lib/python/pyapi.swg @@ -17,30 +17,13 @@ extern "C" { /* Constant information structure */ typedef struct swig_const_info { int type; - char *name; + const char *name; long lvalue; double dvalue; void *pvalue; swig_type_info **ptype; } swig_const_info; - -/* ----------------------------------------------------------------------------- - * Wrapper of PyInstanceMethod_New() used in Python 3 - * It is exported to the generated module, used for -fastproxy - * ----------------------------------------------------------------------------- */ -#if PY_VERSION_HEX >= 0x03000000 -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) -{ - return PyInstanceMethod_New(func); -} -#else -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func)) -{ - return NULL; -} -#endif - #ifdef __cplusplus } #endif diff --git a/Lib/python/pybuffer.i b/Lib/python/pybuffer.i index 121cd709f..577eb69c8 100644 --- a/Lib/python/pybuffer.i +++ b/Lib/python/pybuffer.i @@ -13,10 +13,14 @@ */ %define %pybuffer_mutable_binary(TYPEMAP, SIZE) -%typemap(in) (TYPEMAP, SIZE) - (int res, Py_ssize_t size = 0, void *buf = 0) { - res = PyObject_AsWriteBuffer($input, &buf, &size); - if (res<0) { +%typemap(in) (TYPEMAP, SIZE) { + int res; Py_ssize_t size = 0; void *buf = 0; + Py_buffer view; + res = PyObject_GetBuffer($input, &view, PyBUF_WRITABLE); + size = view.len; + buf = view.buf; + PyBuffer_Release(&view); + if (res < 0) { PyErr_Clear(); %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); } @@ -25,7 +29,7 @@ } %enddef -/* %pybuffer_mutable_string(TYPEMAP, SIZE) +/* %pybuffer_mutable_string(TYPEMAP) * * Macro for functions accept mutable zero terminated string pointer. * This can be used for both input and output. For example: @@ -39,12 +43,15 @@ */ %define %pybuffer_mutable_string(TYPEMAP) -%typemap(in) (TYPEMAP) - (int res, Py_ssize_t size = 0, void *buf = 0) { - res = PyObject_AsWriteBuffer($input, &buf, &size); - if (res<0) { +%typemap(in) (TYPEMAP) { + int res; void *buf = 0; + Py_buffer view; + res = PyObject_GetBuffer($input, &view, PyBUF_WRITABLE); + buf = view.buf; + PyBuffer_Release(&view); + if (res < 0) { PyErr_Clear(); - %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); + %argument_fail(res, "(TYPEMAP)", $symname, $argnum); } $1 = ($1_ltype) buf; } @@ -65,10 +72,14 @@ */ %define %pybuffer_binary(TYPEMAP, SIZE) -%typemap(in) (TYPEMAP, SIZE) - (int res, Py_ssize_t size = 0, const void *buf = 0) { - res = PyObject_AsReadBuffer($input, &buf, &size); - if (res<0) { +%typemap(in) (TYPEMAP, SIZE) { + int res; Py_ssize_t size = 0; const void *buf = 0; + Py_buffer view; + res = PyObject_GetBuffer($input, &view, PyBUF_CONTIG_RO); + size = view.len; + buf = view.buf; + PyBuffer_Release(&view); + if (res < 0) { PyErr_Clear(); %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); } @@ -77,7 +88,7 @@ } %enddef -/* %pybuffer_string(TYPEMAP, SIZE) +/* %pybuffer_string(TYPEMAP) * * Macro for functions accept read only zero terminated string pointer. * This can be used for input. For example: @@ -93,11 +104,14 @@ */ %define %pybuffer_string(TYPEMAP) -%typemap(in) (TYPEMAP) - (int res, Py_ssize_t size = 0, const void *buf = 0) { - res = PyObject_AsReadBuffer($input, &buf, &size); - if (res<0) { - %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); +%typemap(in) (TYPEMAP) { + int res; const void *buf = 0; + Py_buffer view; + res = PyObject_GetBuffer($input, &view, PyBUF_CONTIG_RO); + buf = view.buf; + PyBuffer_Release(&view); + if (res < 0) { + %argument_fail(res, "(TYPEMAP)", $symname, $argnum); } $1 = ($1_ltype) buf; } diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg index 8463e28f8..ef2f725af 100644 --- a/Lib/python/pycontainer.swg +++ b/Lib/python/pycontainer.swg @@ -36,6 +36,48 @@ %include +%fragment("container_owner_attribute_init", "init") { + // thread safe initialization + swig::container_owner_attribute(); +} + +%fragment("reference_container_owner", "header", fragment="container_owner_attribute_init") { +namespace swig { + static PyObject* container_owner_attribute() { + static PyObject* attr = SWIG_Python_str_FromChar("__swig_container"); + return attr; + } + + template + struct container_owner { + // By default, do not add the back-reference (for value types) + // Specialization below will check the reference for pointer types. + static bool back_reference(PyObject* child, PyObject* owner) { + return false; + } + }; + + template <> + struct container_owner { + /* + * Call to add a back-reference to the owning object when returning a + * reference from a container. Will only set the reference if child + * is a SWIG wrapper object that does not own the pointer. + * + * returns whether the reference was set or not + */ + static bool back_reference(PyObject* child, PyObject* owner) { + SwigPyObject* swigThis = SWIG_Python_GetSwigThis(child); + if (swigThis && (swigThis->own & SWIG_POINTER_OWN) != SWIG_POINTER_OWN) { + PyObject_SetAttr(child, container_owner_attribute(), owner); + return true; + } + return false; + } + }; +} +} + %fragment(SWIG_Traits_frag(swig::SwigPtr_PyObject),"header",fragment="StdTraits") { namespace swig { template <> struct traits { @@ -102,13 +144,13 @@ namespace swig { } } -%fragment("SwigPySequence_Base","header",fragment="") +%fragment("SwigPySequence_Base","header",fragment="",fragment="StdTraits") { %#include namespace std { template <> - struct less : public binary_function + struct less { bool operator()(PyObject * v, PyObject *w) const @@ -133,7 +175,7 @@ namespace std { }; template <> - struct less : public binary_function + struct less { bool operator()(const swig::SwigPtr_PyObject& v, const swig::SwigPtr_PyObject& w) const @@ -143,7 +185,7 @@ namespace std { }; template <> - struct less : public binary_function + struct less { bool operator()(const swig::SwigVar_PyObject& v, const swig::SwigVar_PyObject& w) const @@ -351,7 +393,7 @@ namespace swig { typename Sequence::const_iterator isit = is.begin(); typename Sequence::iterator it = self->begin(); std::advance(it,ii); - for (size_t rc=0; rcend(); ++rc) { *it++ = *isit++; for (Py_ssize_t c=0; c<(step-1) && it != self->end(); ++c) it++; @@ -367,7 +409,7 @@ namespace swig { typename Sequence::const_iterator isit = is.begin(); typename Sequence::reverse_iterator it = self->rbegin(); std::advance(it,size-ii-1); - for (size_t rc=0; rcrend(); ++rc) { *it++ = *isit++; for (Py_ssize_t c=0; c<(-step-1) && it != self->rend(); ++c) it++; @@ -434,8 +476,8 @@ namespace swig { swig::SwigVar_PyObject item = PySequence_GetItem(_seq, _index); try { - return swig::as(item, true); - } catch (std::exception& e) { + return swig::as(item); + } catch (const std::invalid_argument& e) { char msg[1024]; sprintf(msg, "in sequence element %d ", (int)_index); if (!PyErr_Occurred()) { @@ -655,6 +697,14 @@ namespace swig } %define %swig_sequence_iterator(Sequence...) + %swig_sequence_iterator_with_making_function(swig::make_output_iterator,Sequence...) +%enddef + +%define %swig_sequence_forward_iterator(Sequence...) + %swig_sequence_iterator_with_making_function(swig::make_output_forward_iterator,Sequence...) +%enddef + +%define %swig_sequence_iterator_with_making_function(Make_output_iterator,Sequence...) #if defined(SWIG_EXPORT_ITERATOR_METHODS) class iterator; class reverse_iterator; @@ -663,15 +713,15 @@ namespace swig %typemap(out,noblock=1,fragment="SwigPySequence_Cont") iterator, reverse_iterator, const_iterator, const_reverse_iterator { - $result = SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &)), + $result = SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &)), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN); } %typemap(out,noblock=1,fragment="SwigPySequence_Cont") std::pair, std::pair { $result = PyTuple_New(2); - PyTuple_SetItem($result,0,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).first), + PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &).first), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); - PyTuple_SetItem($result,1,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).second), + PyTuple_SetItem($result,1,SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &).second), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); } @@ -680,7 +730,7 @@ namespace swig %typemap(out,noblock=1,fragment="SwigPyPairBoolOutputIterator") std::pair, std::pair { $result = PyTuple_New(2); - PyTuple_SetItem($result,0,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).first), + PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &).first), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); PyTuple_SetItem($result,1,SWIG_From(bool)(%static_cast($1,const $type &).second)); } @@ -715,7 +765,7 @@ namespace swig %newobject iterator(PyObject **PYTHON_SELF); %extend { swig::SwigPyIterator* iterator(PyObject **PYTHON_SELF) { - return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + return Make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } #if defined(SWIGPYTHON_BUILTIN) @@ -758,6 +808,12 @@ namespace swig size_type __len__() const { return self->size(); } + + // Although __getitem__, front, back actually use a const value_type& return type, the typemaps below + // use non-const so that they can be easily overridden by users if necessary. + %typemap(ret, fragment="reference_container_owner", noblock=1) value_type& __getitem__, value_type& front, value_type& back { + (void)swig::container_owner::category>::back_reference($result, $self); + } } %enddef @@ -1012,7 +1068,7 @@ namespace swig { %#ifdef SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS swig_type_info *desc = swig::type_info(); if (desc && desc->clientdata) { - return SWIG_NewPointerObj(new sequence(seq), desc, SWIG_POINTER_OWN); + return SWIG_InternalNewPointerObj(new sequence(seq), desc, SWIG_POINTER_OWN); } %#endif size_type size = seq.size(); diff --git a/Lib/python/pydocs.swg b/Lib/python/pydocs.swg index 969af92aa..1eea41b8d 100644 --- a/Lib/python/pydocs.swg +++ b/Lib/python/pydocs.swg @@ -22,3 +22,24 @@ %typemap(doc) SWIGTYPE *INPUT, SWIGTYPE &INPUT "$1_name: $1_type (input)"; %typemap(doc) SWIGTYPE *OUTPUT, SWIGTYPE &OUTPUT "$1_name: $1_type (output)"; #endif + + +// Types to use in Python documentation for the parameters of the given C++ type. +%typemap(doctype) bool "boolean"; + +%define int_doctype_for_cppint_type(cppint_type) + %typemap(doctype) cppint_type, unsigned cppint_type "int"; +%enddef +%formacro(int_doctype_for_cppint_type, short, int, long, long long) + +%typemap(doctype) size_t "int"; + +%typemap(doctype) enum SWIGTYPE "int"; + +%typemap(doctype) float, double, long double "float"; + +%typemap(doctype) char*, std::string "string"; + +%typemap(doctype) SWIGTYPE "$1_basetype" +%typemap(doctype) SWIGTYPE * "$typemap(doctype, $*1_ltype)" +%typemap(doctype) SWIGTYPE & "$typemap(doctype, $*1_ltype)" diff --git a/Lib/python/pyerrors.swg b/Lib/python/pyerrors.swg index fe7313554..dcd99c939 100644 --- a/Lib/python/pyerrors.swg +++ b/Lib/python/pyerrors.swg @@ -53,14 +53,17 @@ SWIG_Python_AddErrorMsg(const char* mesg) PyObject *value = 0; PyObject *traceback = 0; - if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); + if (PyErr_Occurred()) + PyErr_Fetch(&type, &value, &traceback); if (value) { - char *tmp; PyObject *old_str = PyObject_Str(value); + const char *tmp = SWIG_Python_str_AsChar(old_str); PyErr_Clear(); Py_XINCREF(type); - - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); + if (tmp) + PyErr_Format(type, "%s %s", tmp, mesg); + else + PyErr_Format(type, "%s", mesg); SWIG_Python_str_DelForPy3(tmp); Py_DECREF(old_str); Py_DECREF(value); @@ -68,3 +71,34 @@ SWIG_Python_AddErrorMsg(const char* mesg) PyErr_SetString(PyExc_RuntimeError, mesg); } } + +SWIGRUNTIME int +SWIG_Python_TypeErrorOccurred(PyObject *obj) +{ + PyObject *error; + if (obj) + return 0; + error = PyErr_Occurred(); + return error && PyErr_GivenExceptionMatches(error, PyExc_TypeError); +} + +SWIGRUNTIME void +SWIG_Python_RaiseOrModifyTypeError(const char *message) +{ + if (SWIG_Python_TypeErrorOccurred(NULL)) { + /* Use existing TypeError to preserve stacktrace and enhance with given message */ + PyObject *newvalue; + PyObject *type = NULL, *value = NULL, *traceback = NULL; + PyErr_Fetch(&type, &value, &traceback); +#if PY_VERSION_HEX >= 0x03000000 + newvalue = PyUnicode_FromFormat("%S\nAdditional information:\n%s", value, message); +#else + newvalue = PyString_FromFormat("%s\nAdditional information:\n%s", PyString_AsString(value), message); +#endif + Py_XDECREF(value); + PyErr_Restore(type, newvalue, traceback); + } else { + /* Raise TypeError using given message */ + PyErr_SetString(PyExc_TypeError, message); + } +} diff --git a/Lib/python/pyhead.swg b/Lib/python/pyhead.swg index 55eb95a6d..c820f9016 100644 --- a/Lib/python/pyhead.swg +++ b/Lib/python/pyhead.swg @@ -38,14 +38,16 @@ SWIGINTERN char* SWIG_Python_str_AsChar(PyObject *str) { #if PY_VERSION_HEX >= 0x03000000 - char *cstr; - char *newstr; - Py_ssize_t len; + char *newstr = 0; str = PyUnicode_AsUTF8String(str); - PyBytes_AsStringAndSize(str, &cstr, &len); - newstr = (char *) malloc(len+1); - memcpy(newstr, cstr, len+1); - Py_XDECREF(str); + if (str) { + char *cstr; + Py_ssize_t len; + PyBytes_AsStringAndSize(str, &cstr, &len); + newstr = (char *) malloc(len+1); + memcpy(newstr, cstr, len+1); + Py_XDECREF(str); + } return newstr; #else return PyString_AsString(str); @@ -69,144 +71,14 @@ SWIG_Python_str_FromChar(const char *c) #endif } -/* Add PyOS_snprintf for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) -# define PyOS_snprintf _snprintf -# else -# define PyOS_snprintf snprintf -# endif -#endif - -/* A crude PyString_FromFormat implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 - -#ifndef SWIG_PYBUFFER_SIZE -# define SWIG_PYBUFFER_SIZE 1024 -#endif - -static PyObject * -PyString_FromFormat(const char *fmt, ...) { - va_list ap; - char buf[SWIG_PYBUFFER_SIZE * 2]; - int res; - va_start(ap, fmt); - res = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf); -} -#endif - #ifndef PyObject_DEL # define PyObject_DEL PyObject_Del #endif -/* A crude PyExc_StopIteration exception for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# ifndef PyExc_StopIteration -# define PyExc_StopIteration PyExc_RuntimeError -# endif -# ifndef PyObject_GenericGetAttr -# define PyObject_GenericGetAttr 0 -# endif -#endif - -/* Py_NotImplemented is defined in 2.1 and up. */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef Py_NotImplemented -# define Py_NotImplemented PyExc_RuntimeError -# endif -#endif - -/* A crude PyString_AsStringAndSize implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef PyString_AsStringAndSize -# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;} -# endif -#endif - -/* PySequence_Size for old Pythons */ -#if PY_VERSION_HEX < 0x02000000 -# ifndef PySequence_Size -# define PySequence_Size PySequence_Length -# endif -#endif - -/* PyBool_FromLong for old Pythons */ -#if PY_VERSION_HEX < 0x02030000 -static -PyObject *PyBool_FromLong(long ok) -{ - PyObject *result = ok ? Py_True : Py_False; - Py_INCREF(result); - return result; -} -#endif - -/* Py_ssize_t for old Pythons */ -/* This code is as recommended by: */ -/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -# define PY_SSIZE_T_MAX INT_MAX -# define PY_SSIZE_T_MIN INT_MIN -typedef inquiry lenfunc; -typedef intargfunc ssizeargfunc; -typedef intintargfunc ssizessizeargfunc; -typedef intobjargproc ssizeobjargproc; -typedef intintobjargproc ssizessizeobjargproc; -typedef getreadbufferproc readbufferproc; -typedef getwritebufferproc writebufferproc; -typedef getsegcountproc segcountproc; -typedef getcharbufferproc charbufferproc; -static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc)) -{ - long result = 0; - PyObject *i = PyNumber_Int(x); - if (i) { - result = PyInt_AsLong(i); - Py_DECREF(i); - } - return result; -} -#endif - -#if PY_VERSION_HEX < 0x02050000 -#define PyInt_FromSize_t(x) PyInt_FromLong((long)x) -#endif - -#if PY_VERSION_HEX < 0x02040000 -#define Py_VISIT(op) \ - do { \ - if (op) { \ - int vret = visit((op), arg); \ - if (vret) \ - return vret; \ - } \ - } while (0) -#endif - -#if PY_VERSION_HEX < 0x02030000 -typedef struct { - PyTypeObject type; - PyNumberMethods as_number; - PyMappingMethods as_mapping; - PySequenceMethods as_sequence; - PyBufferProcs as_buffer; - PyObject *name, *slots; -} PyHeapTypeObject; -#endif - -#if PY_VERSION_HEX < 0x02030000 -typedef destructor freefunc; -#endif - -#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \ - (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \ - (PY_MAJOR_VERSION > 3)) +// SWIGPY_USE_CAPSULE is no longer used within SWIG itself, but some user +// interface files check for it. # define SWIGPY_USE_CAPSULE -# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME) -#endif +# define SWIGPY_CAPSULE_NAME ("swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME) #if PY_VERSION_HEX < 0x03020000 #define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type) diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg index e671731ac..dfbf40b34 100644 --- a/Lib/python/pyinit.swg +++ b/Lib/python/pyinit.swg @@ -8,6 +8,22 @@ %fragment(""); // For offsetof #endif +%insert(runtime) %{ +#ifdef __cplusplus +extern "C" { +#endif + +/* Method creation and docstring support functions */ + +SWIGINTERN PyMethodDef *SWIG_PythonGetProxyDoc(const char *name); +SWIGINTERN PyObject *SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func); +SWIGINTERN PyObject *SWIG_PyStaticMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func); + +#ifdef __cplusplus +} +#endif +%} + %init %{ #ifdef __cplusplus @@ -82,17 +98,6 @@ swig_varlink_str(swig_varlinkobject *v) { return str; } -SWIGINTERN int -swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { - char *tmp; - PyObject *str = swig_varlink_str(v); - fprintf(fp,"Swig global variables "); - fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(str); - return 0; -} - SWIGINTERN void swig_varlink_dealloc(swig_varlinkobject *v) { swig_globalvar *var = v->vars; @@ -151,11 +156,11 @@ swig_varlink_type(void) { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ #endif - (char *)"swigvarlink", /* tp_name */ + "swigvarlink", /* tp_name */ sizeof(swig_varlinkobject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor) swig_varlink_dealloc, /* tp_dealloc */ - (printfunc) swig_varlink_print, /* tp_print */ + 0, /* tp_print */ (getattrfunc) swig_varlink_getattr, /* tp_getattr */ (setattrfunc) swig_varlink_setattr, /* tp_setattr */ 0, /* tp_compare */ @@ -175,15 +180,9 @@ swig_varlink_type(void) { 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 0, /* tp_version_tag */ -#endif #if PY_VERSION_HEX >= 0x03040000 0, /* tp_finalize */ #endif @@ -191,20 +190,14 @@ swig_varlink_type(void) { 0, /* tp_allocs */ 0, /* tp_frees */ 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 0, /* tp_prev */ -#endif 0 /* tp_next */ #endif }; varlink_type = tmp; type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - varlink_type.ob_type = &PyType_Type; -#else if (PyType_Ready(&varlink_type) < 0) return NULL; -#endif } return &varlink_type; } @@ -220,14 +213,14 @@ SWIG_Python_newvarlink(void) { } SWIGINTERN void -SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { +SWIG_Python_addvarlink(PyObject *p, const char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { swig_varlinkobject *v = (swig_varlinkobject *) p; swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); if (gv) { size_t size = strlen(name)+1; gv->name = (char *)malloc(size); if (gv->name) { - strncpy(gv->name,name,size); + memcpy(gv->name, name, size); gv->get_attr = get_attr; gv->set_attr = set_attr; gv->next = v->vars; @@ -238,9 +231,11 @@ SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int SWIGINTERN PyObject * SWIG_globals(void) { - static PyObject *_SWIG_globals = 0; - if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink(); - return _SWIG_globals; + static PyObject *globals = 0; + if (!globals) { + globals = SWIG_newvarlink(); + } + return globals; } /* ----------------------------------------------------------------------------- @@ -306,9 +301,9 @@ SWIG_Python_FixMethods(PyMethodDef *methods, char *ndoc = (char*)malloc(ldoc + lptr + 10); if (ndoc) { char *buff = ndoc; - strncpy(buff, methods[i].ml_doc, ldoc); + memcpy(buff, methods[i].ml_doc, ldoc); buff += ldoc; - strncpy(buff, "swig_ptr: ", 10); + memcpy(buff, "swig_ptr: ", 10); buff += 10; SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); methods[i].ml_doc = ndoc; @@ -319,6 +314,64 @@ SWIG_Python_FixMethods(PyMethodDef *methods, } } +/* ----------------------------------------------------------------------------- + * Method creation and docstring support functions + * ----------------------------------------------------------------------------- */ + +/* ----------------------------------------------------------------------------- + * Function to find the method definition with the correct docstring for the + * proxy module as opposed to the low-level API + * ----------------------------------------------------------------------------- */ + +SWIGINTERN PyMethodDef *SWIG_PythonGetProxyDoc(const char *name) { + /* Find the function in the modified method table */ + size_t offset = 0; + int found = 0; + while (SwigMethods_proxydocs[offset].ml_meth != NULL) { + if (strcmp(SwigMethods_proxydocs[offset].ml_name, name) == 0) { + found = 1; + break; + } + offset++; + } + /* Use the copy with the modified docstring if available */ + return found ? &SwigMethods_proxydocs[offset] : NULL; +} + +/* ----------------------------------------------------------------------------- + * Wrapper of PyInstanceMethod_New() used in Python 3 + * It is exported to the generated module, used for -fastproxy + * ----------------------------------------------------------------------------- */ + +SWIGINTERN PyObject *SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) { + if (PyCFunction_Check(func)) { + PyCFunctionObject *funcobj = (PyCFunctionObject *)func; + PyMethodDef *ml = SWIG_PythonGetProxyDoc(funcobj->m_ml->ml_name); + if (ml) + func = PyCFunction_NewEx(ml, funcobj->m_self, funcobj->m_module); + } +#if PY_VERSION_HEX >= 0x03000000 + return PyInstanceMethod_New(func); +#else + return PyMethod_New(func, NULL, NULL); +#endif +} + +/* ----------------------------------------------------------------------------- + * Wrapper of PyStaticMethod_New() + * It is exported to the generated module, used for -fastproxy + * ----------------------------------------------------------------------------- */ + +SWIGINTERN PyObject *SWIG_PyStaticMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) { + if (PyCFunction_Check(func)) { + PyCFunctionObject *funcobj = (PyCFunctionObject *)func; + PyMethodDef *ml = SWIG_PythonGetProxyDoc(funcobj->m_ml->ml_name); + if (ml) + func = PyCFunction_NewEx(ml, funcobj->m_self, funcobj->m_module); + } + return PyStaticMethod_New(func); +} + #ifdef __cplusplus } #endif @@ -338,20 +391,12 @@ SWIGEXPORT void #endif SWIG_init(void) { - PyObject *m, *d, *md; + PyObject *m, *d, *md, *globals; + #if PY_VERSION_HEX >= 0x03000000 static struct PyModuleDef SWIG_module = { -# if PY_VERSION_HEX >= 0x03020000 PyModuleDef_HEAD_INIT, -# else - { - PyObject_HEAD_INIT(NULL) - NULL, /* m_init */ - 0, /* m_index */ - NULL, /* m_copy */ - }, -# endif - (char *) SWIG_name, + SWIG_name, NULL, -1, SwigMethods, @@ -368,19 +413,19 @@ SWIG_init(void) { (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL }; static SwigPyGetSet thisown_getset_closure = { - (PyCFunction) SwigPyObject_own, - (PyCFunction) SwigPyObject_own + SwigPyObject_own, + SwigPyObject_own }; static PyGetSetDef thisown_getset_def = { (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure }; - PyObject *metatype_args; PyTypeObject *builtin_pytype; int builtin_base_count; swig_type_info *builtin_basetype; PyObject *tuple; PyGetSetDescrObject *static_getset; PyTypeObject *metatype; + PyTypeObject *swigpyobject; SwigPyClientData *cd; PyObject *public_interface, *public_symbol; PyObject *this_descr; @@ -395,14 +440,19 @@ SWIG_init(void) { (void)static_getset; (void)self; - /* metatype is used to implement static member variables. */ - metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type); - assert(metatype_args); - metatype = (PyTypeObject *) PyType_Type.tp_call((PyObject *) &PyType_Type, metatype_args, NULL); + /* Metaclass is used to implement static member variables */ + metatype = SwigPyObjectType(); assert(metatype); - Py_DECREF(metatype_args); - metatype->tp_setattro = (setattrofunc) &SwigPyObjectType_setattro; - assert(PyType_Ready(metatype) >= 0); +#endif + + (void)globals; + + /* Create singletons now to avoid potential deadlocks with multi-threaded usage after module initialization */ + SWIG_This(); + SWIG_Python_TypeCache(); + SwigPyPacked_type(); +#ifndef SWIGPYTHON_BUILTIN + SwigPyObject_type(); #endif /* Fix SwigMethods to carry the callback ptrs when needed */ @@ -411,7 +461,7 @@ SWIG_init(void) { #if PY_VERSION_HEX >= 0x03000000 m = PyModule_Create(&SWIG_module); #else - m = Py_InitModule((char *) SWIG_name, SwigMethods); + m = Py_InitModule(SWIG_name, SwigMethods); #endif md = d = PyModule_GetDict(m); @@ -420,13 +470,15 @@ SWIG_init(void) { SWIG_InitializeModule(0); #ifdef SWIGPYTHON_BUILTIN + swigpyobject = SwigPyObject_TypeOnce(); + SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject"); assert(SwigPyObject_stype); cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; if (!cd) { SwigPyObject_stype->clientdata = &SwigPyObject_clientdata; - SwigPyObject_clientdata.pytype = SwigPyObject_TypeOnce(); - } else if (SwigPyObject_TypeOnce()->tp_basicsize != cd->pytype->tp_basicsize) { + SwigPyObject_clientdata.pytype = swigpyobject; + } else if (swigpyobject->tp_basicsize != cd->pytype->tp_basicsize) { PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules."); # if PY_VERSION_HEX >= 0x03000000 return NULL; diff --git a/Lib/python/pyiterators.swg b/Lib/python/pyiterators.swg index 8fbb31226..cb15e35cd 100644 --- a/Lib/python/pyiterators.swg +++ b/Lib/python/pyiterators.swg @@ -198,16 +198,16 @@ namespace swig { template::value_type, typename FromOper = from_oper > - class SwigPyIteratorOpen_T : public SwigPyIterator_T + class SwigPyForwardIteratorOpen_T : public SwigPyIterator_T { public: FromOper from; typedef OutIterator out_iterator; typedef ValueType value_type; typedef SwigPyIterator_T base; - typedef SwigPyIteratorOpen_T self_type; + typedef SwigPyForwardIteratorOpen_T self_type; - SwigPyIteratorOpen_T(out_iterator curr, PyObject *seq) + SwigPyForwardIteratorOpen_T(out_iterator curr, PyObject *seq) : SwigPyIterator_T(curr, seq) { } @@ -229,6 +229,25 @@ namespace swig { return this; } + }; + + template::value_type, + typename FromOper = from_oper > + class SwigPyIteratorOpen_T : public SwigPyForwardIteratorOpen_T + { + public: + FromOper from; + typedef OutIterator out_iterator; + typedef ValueType value_type; + typedef SwigPyIterator_T base; + typedef SwigPyIteratorOpen_T self_type; + + SwigPyIteratorOpen_T(out_iterator curr, PyObject *seq) + : SwigPyForwardIteratorOpen_T(curr, seq) + { + } + SwigPyIterator *decr(size_t n = 1) { while (n--) { @@ -241,16 +260,16 @@ namespace swig { template::value_type, typename FromOper = from_oper > - class SwigPyIteratorClosed_T : public SwigPyIterator_T + class SwigPyForwardIteratorClosed_T : public SwigPyIterator_T { public: FromOper from; typedef OutIterator out_iterator; typedef ValueType value_type; typedef SwigPyIterator_T base; - typedef SwigPyIteratorClosed_T self_type; + typedef SwigPyForwardIteratorClosed_T self_type; - SwigPyIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) + SwigPyForwardIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) : SwigPyIterator_T(curr, seq), begin(first), end(last) { } @@ -280,10 +299,33 @@ namespace swig { return this; } + protected: + out_iterator begin; + out_iterator end; + }; + + template::value_type, + typename FromOper = from_oper > + class SwigPyIteratorClosed_T : public SwigPyForwardIteratorClosed_T + { + public: + FromOper from; + typedef OutIterator out_iterator; + typedef ValueType value_type; + typedef SwigPyIterator_T base; + typedef SwigPyForwardIteratorClosed_T base0; + typedef SwigPyIteratorClosed_T self_type; + + SwigPyIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) + : SwigPyForwardIteratorClosed_T(curr, first, last, seq) + { + } + SwigPyIterator *decr(size_t n = 1) { while (n--) { - if (base::current == begin) { + if (base::current == base0::begin) { throw stop_iteration(); } else { --base::current; @@ -291,12 +333,16 @@ namespace swig { } return this; } - - private: - out_iterator begin; - out_iterator end; }; + + template + inline SwigPyIterator* + make_output_forward_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, PyObject *seq = 0) + { + return new SwigPyForwardIteratorClosed_T(current, begin, end, seq); + } + template inline SwigPyIterator* make_output_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, PyObject *seq = 0) @@ -304,6 +350,13 @@ namespace swig { return new SwigPyIteratorClosed_T(current, begin, end, seq); } + template + inline SwigPyIterator* + make_output_forward_iterator(const OutIter& current, PyObject *seq = 0) + { + return new SwigPyForwardIteratorOpen_T(current, seq); + } + template inline SwigPyIterator* make_output_iterator(const OutIter& current, PyObject *seq = 0) diff --git a/Lib/python/pyname_compat.i b/Lib/python/pyname_compat.i index 96af343ca..a9630dbe7 100644 --- a/Lib/python/pyname_compat.i +++ b/Lib/python/pyname_compat.i @@ -34,7 +34,7 @@ %inline %{ #define PyMapIterator_T SwigPyMapIterator_T #define PyMapKeyIterator_T SwigPyMapKeyIterator_T -#define PyMapValueIterator_T SwigPyMapValueITerator_T +#define PyMapValueIterator_T SwigPyMapValueIterator_T #define PyObject_ptr SwigPtr_PyObject #define PyObject_var SwigVar_PyObject #define PyOper SwigPyOper @@ -76,7 +76,6 @@ #define PySwigPacked_UnpackData SwigPyPacked_UnpackData #define PySwigPacked_compare SwigPyPacked_compare #define PySwigPacked_dealloc SwigPyPacked_dealloc -#define PySwigPacked_print SwigPyPacked_print #define PySwigPacked_repr SwigPyPacked_repr #define PySwigPacked_str SwigPyPacked_str #define PySwigPacked_type SwigPyPacked_type diff --git a/Lib/python/pyopers.swg b/Lib/python/pyopers.swg index 5fb22354b..fd2fcc581 100644 --- a/Lib/python/pyopers.swg +++ b/Lib/python/pyopers.swg @@ -108,11 +108,6 @@ %pybinoperator(__neg__, *::operator-(), unaryfunc, nb_negative); %pybinoperator(__neg__, *::operator-() const, unaryfunc, nb_negative); %pybinoperator(__mul__, *::operator*, binaryfunc, nb_multiply); -#if defined(SWIGPYTHON_PY3) -%pybinoperator(__truediv__, *::operator/, binaryfunc, nb_divide); -#else -%pybinoperator(__div__, *::operator/, binaryfunc, nb_divide); -#endif %pybinoperator(__mod__, *::operator%, binaryfunc, nb_remainder); %pybinoperator(__lshift__, *::operator<<, binaryfunc, nb_lshift); %pybinoperator(__rshift__, *::operator>>, binaryfunc, nb_rshift); @@ -134,6 +129,7 @@ #if defined(SWIGPYTHON_BUILTIN) %pybinoperator(__nonzero__, *::operator bool, inquiry, nb_nonzero); +%pybinoperator(__truediv__, *::operator/ , binaryfunc, nb_divide); #else %feature("shadow") *::operator bool %{ def __nonzero__(self): @@ -141,6 +137,13 @@ def __nonzero__(self): __bool__ = __nonzero__ %}; %rename(__nonzero__) *::operator bool; +%feature("shadow") *::operator/ %{ +def __truediv__(self, *args): + return $action(self, *args) +__div__ = __truediv__ +%}; +%rename(__truediv__) *::operator/; +%pythonmaybecall *::operator/; #endif /* Ignored operators */ @@ -207,11 +210,6 @@ __bool__ = __nonzero__ %pyinplaceoper(__iadd__ , *::operator +=, binaryfunc, nb_inplace_add); %pyinplaceoper(__isub__ , *::operator -=, binaryfunc, nb_inplace_subtract); %pyinplaceoper(__imul__ , *::operator *=, binaryfunc, nb_inplace_multiply); -#if defined(SWIGPYTHON_PY3) -%pyinplaceoper(__itruediv__ , *::operator /=, binaryfunc, nb_inplace_divide); -#else -%pyinplaceoper(__idiv__ , *::operator /=, binaryfunc, nb_inplace_divide); -#endif %pyinplaceoper(__imod__ , *::operator %=, binaryfunc, nb_inplace_remainder); %pyinplaceoper(__iand__ , *::operator &=, binaryfunc, nb_inplace_and); %pyinplaceoper(__ior__ , *::operator |=, binaryfunc, nb_inplace_or); @@ -219,6 +217,19 @@ __bool__ = __nonzero__ %pyinplaceoper(__ilshift__, *::operator <<=, binaryfunc, nb_inplace_lshift); %pyinplaceoper(__irshift__, *::operator >>=, binaryfunc, nb_inplace_rshift); +/* Special cases */ +#if defined(SWIGPYTHON_BUILTIN) +%pyinplaceoper(__itruediv__ , *::operator /=, binaryfunc, nb_inplace_divide); +#else +%delobject *::operator /=; +%newobject *::operator /=; +%feature("shadow") *::operator /= %{ +def __itruediv__(self, *args): + return $action(self, *args) +__idiv__ = __itruediv__ +%}; +%rename(__itruediv__) *::operator /=; +#endif /* Finally, in python we need to mark the binary operations to fail as 'maybecall' methods */ @@ -233,6 +244,7 @@ __bool__ = __nonzero__ %pybinopermaybecall(neg); %pybinopermaybecall(mul); %pybinopermaybecall(div); +%pybinopermaybecall(truediv); %pybinopermaybecall(mod); %pybinopermaybecall(lshift); %pybinopermaybecall(rshift); diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index ab1237f62..445a1e324 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -7,6 +7,14 @@ * * ----------------------------------------------------------------------------- */ +#if PY_VERSION_HEX < 0x02070000 /* 2.7.0 */ +# error "This version of SWIG only supports Python >= 2.7" +#endif + +#if PY_VERSION_HEX >= 0x03000000 && PY_VERSION_HEX < 0x03020000 +# error "This version of SWIG only supports Python 3 >= 3.2" +#endif + /* Common SWIG API */ /* for raw pointers */ @@ -90,11 +98,7 @@ SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) { SWIGINTERN void SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) { -#if PY_VERSION_HEX < 0x02030000 - PyDict_SetItemString(d, (char *)name, obj); -#else PyDict_SetItemString(d, name, obj); -#endif Py_DECREF(obj); if (public_interface) SwigPyBuiltin_AddPublicSymbol(public_interface, name); @@ -104,11 +108,7 @@ SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *nam SWIGINTERN void SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { -#if PY_VERSION_HEX < 0x02030000 - PyDict_SetItemString(d, (char *)name, obj); -#else PyDict_SetItemString(d, name, obj); -#endif Py_DECREF(obj); } @@ -118,7 +118,6 @@ SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { SWIGINTERN PyObject* SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { -#if !defined(SWIG_PYTHON_OUTPUT_TUPLE) if (!result) { result = obj; } else if (result == Py_None) { @@ -134,29 +133,6 @@ SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { Py_DECREF(obj); } return result; -#else - PyObject* o2; - PyObject* o3; - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyTuple_Check(result)) { - o2 = result; - result = PyTuple_New(1); - PyTuple_SET_ITEM(result, 0, o2); - } - o3 = PyTuple_New(1); - PyTuple_SET_ITEM(o3, 0, obj); - o2 = result; - result = PySequence_Concat(o2, o3); - Py_DECREF(o2); - Py_DECREF(o3); - } - return result; -#endif } /* Unpack the argument tuple */ @@ -208,11 +184,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi } /* A functor is a function object with one single object argument */ -#if PY_VERSION_HEX >= 0x02020000 #define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); -#else -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); -#endif /* Helper for static pointer initialization for both C and C++ code, for example @@ -241,35 +213,6 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi extern "C" { #endif -/* How to access Py_None */ -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# ifndef SWIG_PYTHON_NO_BUILD_NONE -# ifndef SWIG_PYTHON_BUILD_NONE -# define SWIG_PYTHON_BUILD_NONE -# endif -# endif -#endif - -#ifdef SWIG_PYTHON_BUILD_NONE -# ifdef Py_None -# undef Py_None -# define Py_None SWIG_Py_None() -# endif -SWIGRUNTIMEINLINE PyObject * -_SWIG_Py_None(void) -{ - PyObject *none = Py_BuildValue((char*)""); - Py_DECREF(none); - return none; -} -SWIGRUNTIME PyObject * -SWIG_Py_None(void) -{ - static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); - return none; -} -#endif - /* The python void return value */ SWIGRUNTIMEINLINE PyObject * @@ -296,7 +239,10 @@ SWIGRUNTIMEINLINE int SWIG_Python_CheckImplicit(swig_type_info *ty) { SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; - return data ? data->implicitconv : 0; + int fail = data ? data->implicitconv : 0; + if (fail) + PyErr_SetString(PyExc_TypeError, "Implicit conversion is prohibited for explicit constructors."); + return fail; } SWIGRUNTIMEINLINE PyObject * @@ -323,11 +269,7 @@ SwigPyClientData_New(PyObject* obj) data->newargs = obj; Py_INCREF(obj); } else { -#if (PY_VERSION_HEX < 0x02020000) - data->newraw = 0; -#else - data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); -#endif + data->newraw = PyObject_GetAttrString(data->klass, "__new__"); if (data->newraw) { Py_INCREF(data->newraw); data->newargs = PyTuple_New(1); @@ -338,7 +280,7 @@ SwigPyClientData_New(PyObject* obj) Py_INCREF(data->newargs); } /* the destroy method, aka as the C++ delete method */ - data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); + data->destroy = PyObject_GetAttrString(data->klass, "__swig_destroy__"); if (PyErr_Occurred()) { PyErr_Clear(); data->destroy = 0; @@ -347,11 +289,7 @@ SwigPyClientData_New(PyObject* obj) int flags; Py_INCREF(data->destroy); flags = PyCFunction_GET_FLAGS(data->destroy); -#ifdef METH_O data->delargs = !(flags & (METH_O)); -#else - data->delargs = 0; -#endif } else { data->delargs = 0; } @@ -439,20 +377,12 @@ SwigPyObject_hex(SwigPyObject *v) } SWIGRUNTIME PyObject * -#ifdef METH_NOARGS SwigPyObject_repr(SwigPyObject *v) -#else -SwigPyObject_repr(SwigPyObject *v, PyObject *args) -#endif { const char *name = SWIG_TypePrettyName(v->ty); PyObject *repr = SWIG_Python_str_FromFormat("", (name ? name : "unknown"), (void *)v); if (v->next) { -# ifdef METH_NOARGS PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); -# else - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); -# endif # if PY_VERSION_HEX >= 0x03000000 PyObject *joined = PyUnicode_Concat(repr, nrep); Py_DecRef(repr); @@ -465,6 +395,14 @@ SwigPyObject_repr(SwigPyObject *v, PyObject *args) return repr; } +/* We need a version taking two PyObject* parameters so it's a valid + * PyCFunction to use in swigobject_methods[]. */ +SWIGRUNTIME PyObject * +SwigPyObject_repr2(PyObject *v, PyObject *SWIGUNUSEDPARM(args)) +{ + return SwigPyObject_repr((SwigPyObject*)v); +} + SWIGRUNTIME int SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) { @@ -538,14 +476,14 @@ SwigPyObject_dealloc(PyObject *v) PyObject *res; /* PyObject_CallFunction() has the potential to silently drop - the active active exception. In cases of unnamed temporary + the active exception. In cases of unnamed temporary variable or where we just finished iterating over a generator StopIteration will be active right now, and this needs to remain true upon return from SwigPyObject_dealloc. So save and restore. */ - PyObject *val = NULL, *type = NULL, *tb = NULL; - PyErr_Fetch(&val, &type, &tb); + PyObject *type = NULL, *value = NULL, *traceback = NULL; + PyErr_Fetch(&type, &value, &traceback); if (data->delargs) { /* we need to create a temporary object to carry the destroy operation */ @@ -560,7 +498,7 @@ SwigPyObject_dealloc(PyObject *v) if (!res) PyErr_WriteUnraisable(destroy); - PyErr_Restore(val, type, tb); + PyErr_Restore(type, value, traceback); Py_XDECREF(res); } @@ -579,11 +517,6 @@ SWIGRUNTIME PyObject* SwigPyObject_append(PyObject* v, PyObject* next) { SwigPyObject *sobj = (SwigPyObject *) v; -#ifndef METH_O - PyObject *tmp = 0; - if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; - next = tmp; -#endif if (!SwigPyObject_Check(next)) { PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject"); return NULL; @@ -594,11 +527,7 @@ SwigPyObject_append(PyObject* v, PyObject* next) } SWIGRUNTIME PyObject* -#ifdef METH_NOARGS -SwigPyObject_next(PyObject* v) -#else SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif { SwigPyObject *sobj = (SwigPyObject *) v; if (sobj->next) { @@ -610,11 +539,7 @@ SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) } SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_disown(PyObject *v) -#else SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif { SwigPyObject *sobj = (SwigPyObject *)v; sobj->own = 0; @@ -622,11 +547,7 @@ SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) } SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_acquire(PyObject *v) -#else SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif { SwigPyObject *sobj = (SwigPyObject *)v; sobj->own = SWIG_POINTER_OWN; @@ -637,70 +558,32 @@ SWIGINTERN PyObject* SwigPyObject_own(PyObject *v, PyObject *args) { PyObject *val = 0; -#if (PY_VERSION_HEX < 0x02020000) - if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) -#elif (PY_VERSION_HEX < 0x02050000) - if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) -#else - if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) -#endif - { - return NULL; + if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) { + return NULL; + } else { + SwigPyObject *sobj = (SwigPyObject *)v; + PyObject *obj = PyBool_FromLong(sobj->own); + if (val) { + if (PyObject_IsTrue(val)) { + SwigPyObject_acquire(v,args); + } else { + SwigPyObject_disown(v,args); + } } - else - { - SwigPyObject *sobj = (SwigPyObject *)v; - PyObject *obj = PyBool_FromLong(sobj->own); - if (val) { -#ifdef METH_NOARGS - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v); - } else { - SwigPyObject_disown(v); - } -#else - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v,args); - } else { - SwigPyObject_disown(v,args); - } -#endif - } - return obj; - } + return obj; + } } -#ifdef METH_O static PyMethodDef swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_NOARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS, (char *)"acquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_NOARGS, (char *)"returns object representation"}, + {"disown", SwigPyObject_disown, METH_NOARGS, "releases ownership of the pointer"}, + {"acquire", SwigPyObject_acquire, METH_NOARGS, "acquires ownership of the pointer"}, + {"own", SwigPyObject_own, METH_VARARGS, "returns/sets ownership of the pointer"}, + {"append", SwigPyObject_append, METH_O, "appends another 'this' object"}, + {"next", SwigPyObject_next, METH_NOARGS, "returns the next 'this' object"}, + {"__repr__",SwigPyObject_repr2, METH_NOARGS, "returns object representation"}, {0, 0, 0, 0} }; -#else -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"acquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#endif - -#if PY_VERSION_HEX < 0x02020000 -SWIGINTERN PyObject * -SwigPyObject_getattr(SwigPyObject *sobj,char *name) -{ - return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); -} -#endif SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void) { @@ -745,12 +628,8 @@ SwigPyObject_TypeOnce(void) { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */ #elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ -#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ +#else 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ -#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ -#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ - 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ #endif }; @@ -764,16 +643,12 @@ SwigPyObject_TypeOnce(void) { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ #endif - (char *)"SwigPyObject", /* tp_name */ + "SwigPyObject", /* tp_name */ sizeof(SwigPyObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)SwigPyObject_dealloc, /* tp_dealloc */ 0, /* tp_print */ -#if PY_VERSION_HEX < 0x02020000 - (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ -#else (getattrfunc)0, /* tp_getattr */ -#endif (setattrfunc)0, /* tp_setattr */ #if PY_VERSION_HEX >= 0x03000000 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ @@ -796,7 +671,6 @@ SwigPyObject_TypeOnce(void) { 0, /* tp_clear */ (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */ 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 0, /* tp_iter */ 0, /* tp_iternext */ swigobject_methods, /* tp_methods */ @@ -817,13 +691,8 @@ SwigPyObject_TypeOnce(void) { 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 0, /* tp_version_tag */ -#endif #if PY_VERSION_HEX >= 0x03040000 0, /* tp_finalize */ #endif @@ -831,20 +700,14 @@ SwigPyObject_TypeOnce(void) { 0, /* tp_allocs */ 0, /* tp_frees */ 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 0, /* tp_prev */ -#endif 0 /* tp_next */ #endif }; swigpyobject_type = tmp; type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - swigpyobject_type.ob_type = &PyType_Type; -#else if (PyType_Ready(&swigpyobject_type) < 0) return NULL; -#endif } return &swigpyobject_type; } @@ -873,20 +736,6 @@ typedef struct { size_t size; } SwigPyPacked; -SWIGRUNTIME int -SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) -{ - char result[SWIG_BUFFER_SIZE]; - fputs("pack, v->size, 0, sizeof(result))) { - fputs("at ", fp); - fputs(result, fp); - } - fputs(v->ty->name,fp); - fputs(">", fp); - return 0; -} - SWIGRUNTIME PyObject * SwigPyPacked_repr(SwigPyPacked *v) { @@ -915,7 +764,7 @@ SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) size_t i = v->size; size_t j = w->size; int s = (i < j) ? -1 : ((i > j) ? 1 : 0); - return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); + return s ? s : strncmp((const char *)v->pack, (const char *)w->pack, 2*v->size); } SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void); @@ -955,11 +804,11 @@ SwigPyPacked_TypeOnce(void) { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ #endif - (char *)"SwigPyPacked", /* tp_name */ + "SwigPyPacked", /* tp_name */ sizeof(SwigPyPacked), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ - (printfunc)SwigPyPacked_print, /* tp_print */ + 0, /* tp_print */ (getattrfunc)0, /* tp_getattr */ (setattrfunc)0, /* tp_setattr */ #if PY_VERSION_HEX>=0x03000000 @@ -983,7 +832,6 @@ SwigPyPacked_TypeOnce(void) { 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ @@ -1004,13 +852,8 @@ SwigPyPacked_TypeOnce(void) { 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 0, /* tp_version_tag */ -#endif #if PY_VERSION_HEX >= 0x03040000 0, /* tp_finalize */ #endif @@ -1018,20 +861,14 @@ SwigPyPacked_TypeOnce(void) { 0, /* tp_allocs */ 0, /* tp_frees */ 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 0, /* tp_prev */ -#endif 0 /* tp_next */ #endif }; swigpypacked_type = tmp; type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - swigpypacked_type.ob_type = &PyType_Type; -#else if (PyType_Ready(&swigpypacked_type) < 0) return NULL; -#endif } return &swigpypacked_type; } @@ -1072,20 +909,14 @@ SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) * pointers/data manipulation * ----------------------------------------------------------------------------- */ -SWIGRUNTIMEINLINE PyObject * -_SWIG_This(void) -{ - return SWIG_Python_str_FromChar("this"); -} - -static PyObject *swig_this = NULL; +static PyObject *Swig_This_global = NULL; SWIGRUNTIME PyObject * SWIG_This(void) { - if (swig_this == NULL) - swig_this = _SWIG_This(); - return swig_this; + if (Swig_This_global == NULL) + Swig_This_global = SWIG_Python_str_FromChar("this"); + return Swig_This_global; } /* #define SWIG_PYTHON_SLOW_GETSET_THIS */ @@ -1117,7 +948,7 @@ SWIG_Python_GetSwigThis(PyObject *pyobj) obj = 0; -#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) +#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) if (PyInstance_Check(pyobj)) { obj = _PyInstance_Lookup(pyobj, SWIG_This()); } else { @@ -1187,7 +1018,7 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int if (obj == Py_None && !implicit_conv) { if (ptr) *ptr = 0; - return SWIG_OK; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } res = SWIG_ERROR; @@ -1267,13 +1098,13 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int } } } - } - if (!SWIG_IsOK(res) && obj == Py_None) { - if (ptr) - *ptr = 0; - if (PyErr_Occurred()) - PyErr_Clear(); - res = SWIG_OK; + if (!SWIG_IsOK(res) && obj == Py_None) { + if (ptr) + *ptr = 0; + if (PyErr_Occurred()) + PyErr_Clear(); + res = SWIG_OK; + } } } return res; @@ -1287,31 +1118,28 @@ SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { return SWIG_ConvertPtr(obj, ptr, ty, 0); } else { void *vptr = 0; - + swig_cast_info *tc; + /* here we get the method pointer for callbacks */ const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; if (desc) desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; - if (!desc) + if (!desc) return SWIG_ERROR; - if (ty) { - swig_cast_info *tc = SWIG_TypeCheck(desc,ty); - if (tc) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - } else { - return SWIG_ERROR; - } + tc = SWIG_TypeCheck(desc,ty); + if (tc) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ } else { - *ptr = vptr; + return SWIG_ERROR; } return SWIG_OK; } } -/* Convert a packed value value */ +/* Convert a packed pointer value */ SWIGRUNTIME int SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { @@ -1339,7 +1167,6 @@ SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *t SWIGRUNTIME PyObject* SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) { -#if (PY_VERSION_HEX >= 0x02020000) PyObject *inst = 0; PyObject *newraw = data->newraw; if (newraw) { @@ -1362,10 +1189,18 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) } } else { #if PY_VERSION_HEX >= 0x03000000 - inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); - if (inst) { - PyObject_SetAttr(inst, SWIG_This(), swig_this); - Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; + PyObject *empty_args = PyTuple_New(0); + if (empty_args) { + PyObject *empty_kwargs = PyDict_New(); + if (empty_kwargs) { + inst = ((PyTypeObject *)data->newargs)->tp_new((PyTypeObject *)data->newargs, empty_args, empty_kwargs); + Py_DECREF(empty_kwargs); + if (inst) { + PyObject_SetAttr(inst, SWIG_This(), swig_this); + Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; + } + } + Py_DECREF(empty_args); } #else PyObject *dict = PyDict_New(); @@ -1377,45 +1212,13 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) #endif } return inst; -#else -#if (PY_VERSION_HEX >= 0x02010000) - PyObject *inst = 0; - PyObject *dict = PyDict_New(); - if (dict) { - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - } - return (PyObject *) inst; -#else - PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); - if (inst == NULL) { - return NULL; - } - inst->in_class = (PyClassObject *)data->newargs; - Py_INCREF(inst->in_class); - inst->in_dict = PyDict_New(); - if (inst->in_dict == NULL) { - Py_DECREF(inst); - return NULL; - } -#ifdef Py_TPFLAGS_HAVE_WEAKREFS - inst->in_weakreflist = NULL; -#endif -#ifdef Py_TPFLAGS_GC - PyObject_GC_Init(inst); -#endif - PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); - return (PyObject *) inst; -#endif -#endif } SWIGRUNTIME void SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) { PyObject *dict; -#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) +#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) PyObject **dictptr = _PyObject_GetDictPtr(inst); if (dictptr != NULL) { dict = *dictptr; @@ -1427,7 +1230,7 @@ SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) return; } #endif - dict = PyObject_GetAttrString(inst, (char*)"__dict__"); + dict = PyObject_GetAttrString(inst, "__dict__"); PyDict_SetItem(dict, SWIG_This(), swig_this); Py_DECREF(dict); } @@ -1526,12 +1329,7 @@ SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { #ifdef SWIG_LINK_RUNTIME type_pointer = SWIG_ReturnGlobalTypeList((void *)0); #else -# ifdef SWIGPY_USE_CAPSULE type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0); -# else - type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, - (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); -# endif if (PyErr_Occurred()) { PyErr_Clear(); type_pointer = (void *)0; @@ -1541,48 +1339,10 @@ SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { return (swig_module_info *) type_pointer; } -#if PY_MAJOR_VERSION < 2 -/* PyModule_AddObject function was introduced in Python 2.0. The following function - is copied out of Python/modsupport.c in python version 2.3.4 */ -SWIGINTERN int -PyModule_AddObject(PyObject *m, char *name, PyObject *o) -{ - PyObject *dict; - if (!PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg"); - return SWIG_ERROR; - } - if (!o) { - PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value"); - return SWIG_ERROR; - } - - dict = PyModule_GetDict(m); - if (dict == NULL) { - /* Internal error -- modules must have a dict! */ - PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", - PyModule_GetName(m)); - return SWIG_ERROR; - } - if (PyDict_SetItemString(dict, name, o)) - return SWIG_ERROR; - Py_DECREF(o); - return SWIG_OK; -} -#endif - SWIGRUNTIME void -#ifdef SWIGPY_USE_CAPSULE SWIG_Python_DestroyModule(PyObject *obj) -#else -SWIG_Python_DestroyModule(void *vptr) -#endif { -#ifdef SWIGPY_USE_CAPSULE swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME); -#else - swig_module_info *swig_module = (swig_module_info *) vptr; -#endif swig_type_info **types = swig_module->types; size_t i; for (i =0; i < swig_module->size; ++i) { @@ -1593,33 +1353,24 @@ SWIG_Python_DestroyModule(void *vptr) } } Py_DECREF(SWIG_This()); - swig_this = NULL; + Swig_This_global = NULL; } SWIGRUNTIME void SWIG_Python_SetModule(swig_module_info *swig_module) { #if PY_VERSION_HEX >= 0x03000000 /* Add a dummy module object into sys.modules */ - PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); + PyObject *module = PyImport_AddModule("swig_runtime_data" SWIG_RUNTIME_VERSION); #else static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */ - PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table); + PyObject *module = Py_InitModule("swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table); #endif -#ifdef SWIGPY_USE_CAPSULE PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule); if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer); + PyModule_AddObject(module, "type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer); } else { Py_XDECREF(pointer); } -#else - PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -#endif } /* The python cached type query */ @@ -1637,20 +1388,12 @@ SWIG_Python_TypeQuery(const char *type) PyObject *obj = PyDict_GetItem(cache, key); swig_type_info *descriptor; if (obj) { -#ifdef SWIGPY_USE_CAPSULE descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL); -#else - descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); -#endif } else { swig_module_info *swig_module = SWIG_GetModule(0); descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); if (descriptor) { -#ifdef SWIGPY_USE_CAPSULE obj = PyCapsule_New((void*) descriptor, NULL, NULL); -#else - obj = PyCObject_FromVoidPtr(descriptor, NULL); -#endif PyDict_SetItem(cache, key, obj); Py_DECREF(obj); } @@ -1675,14 +1418,15 @@ SWIG_Python_AddErrMesg(const char* mesg, int infront) PyObject *traceback = 0; PyErr_Fetch(&type, &value, &traceback); if (value) { - char *tmp; PyObject *old_str = PyObject_Str(value); + const char *tmp = SWIG_Python_str_AsChar(old_str); + const char *errmesg = tmp ? tmp : "Invalid error message"; Py_XINCREF(type); PyErr_Clear(); if (infront) { - PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); + PyErr_Format(type, "%s %s", mesg, errmesg); } else { - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); + PyErr_Format(type, "%s %s", errmesg, mesg); } SWIG_Python_str_DelForPy3(tmp); Py_DECREF(old_str); @@ -1808,6 +1552,8 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { Py_INCREF(name); } else { encoded_name = PyUnicode_AsUTF8String(name); + if (!encoded_name) + return -1; } PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name)); Py_DECREF(encoded_name); diff --git a/Lib/python/pyruntime.swg b/Lib/python/pyruntime.swg index fad97be9f..751bc8d5f 100644 --- a/Lib/python/pyruntime.swg +++ b/Lib/python/pyruntime.swg @@ -1,9 +1,14 @@ %insert(runtime) %{ +#if defined(__GNUC__) && defined(_WIN32) && !defined(SWIG_PYTHON_NO_HYPOT_WORKAROUND) +/* Workaround for '::hypot' has not been declared', see https://bugs.python.org/issue11566 */ +# include +#endif + #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG) /* Use debug wrappers with the Python release dll */ # undef _DEBUG # include -# define _DEBUG +# define _DEBUG 1 #else # include #endif diff --git a/Lib/python/pystdcommon.swg b/Lib/python/pystdcommon.swg index 8372426a0..0242e4d35 100644 --- a/Lib/python/pystdcommon.swg +++ b/Lib/python/pystdcommon.swg @@ -45,7 +45,7 @@ namespace swig { template struct traits_asptr { static int asptr(PyObject *obj, Type **val) { - Type *p; + Type *p = 0; swig_type_info *descriptor = type_info(); int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; if (SWIG_IsOK(res)) { @@ -107,14 +107,14 @@ namespace swig { template struct traits_as { - static Type as(PyObject *obj, bool throw_error) { + static Type as(PyObject *obj) { Type v; int res = asval(obj, &v); if (!obj || !SWIG_IsOK(res)) { if (!PyErr_Occurred()) { ::%type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); + throw std::invalid_argument("bad type"); } return v; } @@ -122,7 +122,7 @@ namespace swig { template struct traits_as { - static Type as(PyObject *obj, bool throw_error) { + static Type as(PyObject *obj) { Type *v = 0; int res = (obj ? traits_asptr::asptr(obj, &v) : SWIG_ERROR); if (SWIG_IsOK(res) && v) { @@ -134,21 +134,17 @@ namespace swig { return *v; } } else { - // Uninitialized return value, no Type() constructor required. - static Type *v_def = (Type*) malloc(sizeof(Type)); if (!PyErr_Occurred()) { %type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); - memset(v_def,0,sizeof(Type)); - return *v_def; + throw std::invalid_argument("bad type"); } } }; template struct traits_as { - static Type* as(PyObject *obj, bool throw_error) { + static Type* as(PyObject *obj) { Type *v = 0; int res = (obj ? traits_asptr::asptr(obj, &v) : SWIG_ERROR); if (SWIG_IsOK(res)) { @@ -157,15 +153,14 @@ namespace swig { if (!PyErr_Occurred()) { %type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); - return 0; + throw std::invalid_argument("bad type"); } } }; template - inline Type as(PyObject *obj, bool te = false) { - return traits_as::category>::as(obj, te); + inline Type as(PyObject *obj) { + return traits_as::category>::as(obj); } template diff --git a/Lib/python/pystrings.swg b/Lib/python/pystrings.swg index fd37855eb..93f48acfa 100644 --- a/Lib/python/pystrings.swg +++ b/Lib/python/pystrings.swg @@ -16,6 +16,7 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) %#endif { char *cstr; Py_ssize_t len; + int ret = SWIG_OK; %#if PY_VERSION_HEX>=0x03000000 %#if !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) if (!alloc && cptr) { @@ -26,7 +27,10 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) return SWIG_RuntimeError; } obj = PyUnicode_AsUTF8String(obj); - if(alloc) *alloc = SWIG_NEWOBJ; + if (!obj) + return SWIG_TypeError; + if (alloc) + *alloc = SWIG_NEWOBJ; %#endif PyBytes_AsStringAndSize(obj, &cstr, &len); %#else @@ -34,21 +38,7 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) %#endif if (cptr) { if (alloc) { - /* - In python the user should not be able to modify the inner - string representation. To warranty that, if you define - SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string - buffer is always returned. - - The default behavior is just to return the pointer value, - so, be careful. - */ -%#if defined(SWIG_PYTHON_SAFE_CSTRINGS) - if (*alloc != SWIG_OLDOBJ) -%#else - if (*alloc == SWIG_NEWOBJ) -%#endif - { + if (*alloc == SWIG_NEWOBJ) { *cptr = %new_copy_array(cstr, len + 1, char); *alloc = SWIG_NEWOBJ; } else { @@ -64,6 +54,8 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) %#endif %#else *cptr = SWIG_Python_str_AsChar(obj); + if (!*cptr) + ret = SWIG_TypeError; %#endif } } @@ -71,7 +63,7 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) %#if PY_VERSION_HEX>=0x03000000 && !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) Py_XDECREF(obj); %#endif - return SWIG_OK; + return ret; } else { %#if defined(SWIG_PYTHON_2_UNICODE) %#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) @@ -84,6 +76,8 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) return SWIG_RuntimeError; } obj = PyUnicode_AsUTF8String(obj); + if (!obj) + return SWIG_TypeError; if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) { if (cptr) { if (alloc) *alloc = SWIG_NEWOBJ; @@ -129,11 +123,7 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size) %#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) return PyBytes_FromStringAndSize(carray, %numeric_cast(size, Py_ssize_t)); %#else -%#if PY_VERSION_HEX >= 0x03010000 return PyUnicode_DecodeUTF8(carray, %numeric_cast(size, Py_ssize_t), "surrogateescape"); -%#else - return PyUnicode_FromStringAndSize(carray, %numeric_cast(size, Py_ssize_t)); -%#endif %#endif %#else return PyString_FromStringAndSize(carray, %numeric_cast(size, Py_ssize_t)); diff --git a/Lib/python/pythonkw.swg b/Lib/python/pythonkw.swg index 1a4329d20..0138e40e4 100644 --- a/Lib/python/pythonkw.swg +++ b/Lib/python/pythonkw.swg @@ -14,6 +14,8 @@ PYTHONKW(and); PYTHONKW(as); PYTHONKW(assert); +PYTHONKW(async); +PYTHONKW(await); PYTHONKW(break); PYTHONKW(class); PYTHONKW(continue); diff --git a/Lib/python/pythreads.swg b/Lib/python/pythreads.swg index a7552f1fe..d8797e659 100644 --- a/Lib/python/pythreads.swg +++ b/Lib/python/pythreads.swg @@ -5,9 +5,7 @@ #endif #if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ # if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) -# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ -# define SWIG_PYTHON_USE_GIL -# endif +# define SWIG_PYTHON_USE_GIL # endif # if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ # ifndef SWIG_PYTHON_INITIALIZE_THREADS diff --git a/Lib/python/pytypemaps.swg b/Lib/python/pytypemaps.swg index 48b0bcdc8..0eda17cda 100644 --- a/Lib/python/pytypemaps.swg +++ b/Lib/python/pytypemaps.swg @@ -80,7 +80,7 @@ /* Consttab, needed for callbacks, it should be removed later */ %typemap(consttab) SWIGTYPE ((*)(ANY)) -{ SWIG_PY_POINTER, (char*)"$symname", 0, 0, (void *)($value), &$descriptor } +{ SWIG_PY_POINTER, "$symname", 0, 0, (void *)($value), &$descriptor } %typemap(consttab) SWIGTYPE ((* const)(ANY)) = SWIGTYPE ((*)(ANY)); %typemap(constcode) SWIGTYPE ((*)(ANY)) ""; diff --git a/Lib/python/pyuserdir.swg b/Lib/python/pyuserdir.swg index 00aec07d5..311076079 100644 --- a/Lib/python/pyuserdir.swg +++ b/Lib/python/pyuserdir.swg @@ -41,9 +41,6 @@ The implementation is based on this recipe: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252158 -and works for modern (-modern) and plain python. We do not use __slots__, -so, it works with old python versions. - */ #define %pythonnondynamic %feature("python:nondynamic", "1") @@ -163,7 +160,7 @@ These methods "may be called" if needed. /* ------------------------------------------------------------------------- */ /* - Enable keywords paramaters + Enable keywords parameters */ #define %kwargs %feature("kwargs") diff --git a/Lib/python/pywstrings.swg b/Lib/python/pywstrings.swg index e64618762..0e5a78df5 100644 --- a/Lib/python/pywstrings.swg +++ b/Lib/python/pywstrings.swg @@ -18,16 +18,32 @@ SWIG_AsWCharPtrAndSize(PyObject *obj, wchar_t **cptr, size_t *psize, int *alloc) int isunicode = PyUnicode_Check(obj); %#if PY_VERSION_HEX < 0x03000000 && !defined(SWIG_PYTHON_STRICT_UNICODE_WCHAR) if (!isunicode && PyString_Check(obj)) { - obj = tmp = PyUnicode_FromObject(obj); - isunicode = 1; + tmp = PyUnicode_FromObject(obj); + if (tmp) { + isunicode = 1; + obj = tmp; + } else { + PyErr_Clear(); + return SWIG_TypeError; + } } %#endif if (isunicode) { +%#if PY_VERSION_HEX >= 0x03030000 + Py_ssize_t len = PyUnicode_GetLength(obj); +%#else Py_ssize_t len = PyUnicode_GetSize(obj); +%#endif if (cptr) { + Py_ssize_t length; *cptr = %new_array(len + 1, wchar_t); - PyUnicode_AsWideChar(SWIGPY_UNICODE_ARG(obj), *cptr, len); - (*cptr)[len] = 0; + length = PyUnicode_AsWideChar(SWIGPY_UNICODE_ARG(obj), *cptr, len); + if (length == -1) { + PyErr_Clear(); + Py_XDECREF(tmp); + return SWIG_TypeError; + } + (*cptr)[length] = 0; } if (psize) *psize = (size_t) len + 1; if (alloc) *alloc = cptr ? SWIG_NEWOBJ : 0; diff --git a/Lib/python/std_array.i b/Lib/python/std_array.i index bad818be7..a3de3125b 100644 --- a/Lib/python/std_array.i +++ b/Lib/python/std_array.i @@ -45,11 +45,11 @@ Difference jj = 0; swig::slice_adjust(i, j, step, size, ii, jj); - if (step == 1 && ii == 0 && jj == size) { + if (step == 1 && ii == 0 && static_cast(jj) == size) { Sequence *sequence = new Sequence(); std::copy(self->begin(), self->end(), sequence->begin()); return sequence; - } else if (step == -1 && ii == (size - 1) && jj == -1) { + } else if (step == -1 && static_cast(ii) == (size - 1) && jj == -1) { Sequence *sequence = new Sequence(); std::copy(self->rbegin(), self->rend(), sequence->begin()); return sequence; @@ -67,9 +67,9 @@ Difference jj = 0; swig::slice_adjust(i, j, step, size, ii, jj, true); - if (step == 1 && ii == 0 && jj == size) { + if (step == 1 && ii == 0 && static_cast(jj) == size) { std::copy(is.begin(), is.end(), self->begin()); - } else if (step == -1 && ii == (size - 1) && jj == -1) { + } else if (step == -1 && static_cast(ii) == (size - 1) && jj == -1) { std::copy(is.rbegin(), is.rend(), self->begin()); } else { throw std::invalid_argument("std::array object only supports setting a slice that is the size of the array"); diff --git a/Lib/python/std_basic_string.i b/Lib/python/std_basic_string.i index 7d3366db5..e3f524dbd 100644 --- a/Lib/python/std_basic_string.i +++ b/Lib/python/std_basic_string.i @@ -9,41 +9,34 @@ %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsCharPtrAndSize") { SWIGINTERN int -SWIG_AsPtr(std::basic_string)(PyObject* obj, std::string **val) -{ - static swig_type_info* string_info = - SWIG_TypeQuery("std::basic_string *"); - std::string *vptr; - if (SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0) == SWIG_OK) { +SWIG_AsPtr(std::basic_string)(PyObject* obj, std::string **val) { + static swig_type_info* string_info = SWIG_TypeQuery("std::basic_string *"); + std::string *vptr; + if (SWIG_IsOK(SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0))) { if (val) *val = vptr; return SWIG_OLDOBJ; } else { PyErr_Clear(); char* buf = 0 ; size_t size = 0; int alloc = 0; - if (SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc) == SWIG_OK) { + if (SWIG_IsOK(SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc))) { if (buf) { if (val) *val = new std::string(buf, size - 1); if (alloc == SWIG_NEWOBJ) %delete_array(buf); return SWIG_NEWOBJ; + } else { + if (val) *val = 0; + return SWIG_OLDOBJ; } - } else { - PyErr_Clear(); - } - if (val) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(PyExc_TypeError,"a string is expected"); - SWIG_PYTHON_THREAD_END_BLOCK; } - return 0; + return SWIG_ERROR; } -} +} } %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromCharPtrAndSize") { SWIGINTERNINLINE PyObject* - SWIG_From(std::basic_string)(const std::string& s) - { + SWIG_From(std::basic_string)(const std::string& s) { return SWIG_FromCharPtrAndSize(s.data(), s.size()); } } @@ -59,41 +52,34 @@ SWIGINTERNINLINE PyObject* %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsWCharPtrAndSize") { SWIGINTERN int - SWIG_AsPtr(std::basic_string)(PyObject* obj, std::wstring **val) - { - static swig_type_info* string_info = - SWIG_TypeQuery("std::basic_string *"); - std::wstring *vptr; - if (SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0) == SWIG_OK) { - if (val) *val = vptr; - return SWIG_OLDOBJ; - } else { - PyErr_Clear(); - wchar_t *buf = 0 ; size_t size = 0; int alloc = 0; - if (SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc) == SWIG_OK) { - if (buf) { - if (val) *val = new std::wstring(buf, size - 1); - if (alloc == SWIG_NEWOBJ) %delete_array(buf); - return SWIG_NEWOBJ; - } +SWIG_AsPtr(std::basic_string)(PyObject* obj, std::wstring **val) { + static swig_type_info* string_info = SWIG_TypeQuery("std::basic_string *"); + std::wstring *vptr; + if (SWIG_IsOK(SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0))) { + if (val) *val = vptr; + return SWIG_OLDOBJ; + } else { + PyErr_Clear(); + wchar_t *buf = 0 ; size_t size = 0; int alloc = 0; + if (SWIG_IsOK(SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc))) { + if (buf) { + if (val) *val = new std::wstring(buf, size - 1); + if (alloc == SWIG_NEWOBJ) %delete_array(buf); + return SWIG_NEWOBJ; } else { - PyErr_Clear(); - } - if (val) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(PyExc_TypeError,"a wstring is expected"); - SWIG_PYTHON_THREAD_END_BLOCK; + if (val) *val = 0; + return SWIG_OLDOBJ; } - return 0; } + return SWIG_ERROR; } } +} %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromWCharPtrAndSize") { SWIGINTERNINLINE PyObject* - SWIG_From(std::basic_string)(const std::wstring& s) - { + SWIG_From(std::basic_string)(const std::wstring& s) { return SWIG_FromWCharPtrAndSize(s.data(), s.size()); } } diff --git a/Lib/python/std_complex.i b/Lib/python/std_complex.i index 4e8fed305..c9c46c4c3 100644 --- a/Lib/python/std_complex.i +++ b/Lib/python/std_complex.i @@ -8,6 +8,13 @@ #include %} +namespace std { + %naturalvar complex; + template class complex; + %template() complex; + %template() complex; +} + /* defining the complex as/from converters */ %swig_cplxdbl_convn(std::complex, std::complex, std::real, std::imag) @@ -18,5 +25,3 @@ %typemaps_primitive(%checkcode(CPLXDBL), std::complex); %typemaps_primitive(%checkcode(CPLXFLT), std::complex); - - diff --git a/Lib/python/std_deque.i b/Lib/python/std_deque.i index b19375633..d9a174706 100644 --- a/Lib/python/std_deque.i +++ b/Lib/python/std_deque.i @@ -14,7 +14,7 @@ template struct traits_from > { - static PyObject *from(const std::deque & vec) { + static PyObject *from(const std::deque& vec) { return traits_from_stdseq >::from(vec); } }; diff --git a/Lib/python/std_list.i b/Lib/python/std_list.i index baf66d914..24d274b42 100644 --- a/Lib/python/std_list.i +++ b/Lib/python/std_list.i @@ -14,7 +14,7 @@ template struct traits_from > { - static PyObject *from(const std::list & vec) { + static PyObject *from(const std::list& vec) { return traits_from_stdseq >::from(vec); } }; diff --git a/Lib/python/std_map.i b/Lib/python/std_map.i index f61f79c44..8ae483cef 100644 --- a/Lib/python/std_map.i +++ b/Lib/python/std_map.i @@ -56,9 +56,9 @@ template > - struct SwigPyMapValueITerator_T : SwigPyMapIterator_T + struct SwigPyMapValueIterator_T : SwigPyMapIterator_T { - SwigPyMapValueITerator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) + SwigPyMapValueIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) : SwigPyMapIterator_T(curr, first, last, seq) { } @@ -69,7 +69,7 @@ inline SwigPyIterator* make_output_value_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) { - return new SwigPyMapValueITerator_T(current, begin, end, seq); + return new SwigPyMapValueIterator_T(current, begin, end, seq); } } } @@ -156,6 +156,7 @@ %feature("python:slot", "mp_length", functype="lenfunc") __len__; %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__; %feature("python:slot", "tp_iter", functype="getiterfunc") key_iterator; + %feature("python:slot", "sq_contains", functype="objobjproc") __contains__; %extend { %newobject iterkeys(PyObject **PYTHON_SELF); @@ -263,7 +264,6 @@ return itemList; } - // Python 2.2 methods bool __contains__(const key_type& key) { return self->find(key) != self->end(); } diff --git a/Lib/python/std_multimap.i b/Lib/python/std_multimap.i index 3209fb0f8..f78a5277c 100644 --- a/Lib/python/std_multimap.i +++ b/Lib/python/std_multimap.i @@ -23,7 +23,11 @@ int res = SWIG_ERROR; if (PyDict_Check(obj)) { SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL); - return traits_asptr_stdseq, std::pair >::asptr(items, val); +%#if PY_VERSION_HEX >= 0x03000000 + /* In Python 3.x the ".items()" method returns a dict_items object */ + items = PySequence_Fast(items, ".items() didn't return a sequence!"); +%#endif + res = traits_asptr_stdseq, std::pair >::asptr(items, val); } else { multimap_type *p; swig_type_info *descriptor = swig::type_info(); @@ -68,7 +72,17 @@ %define %swig_multimap_methods(Type...) %swig_map_common(Type); + +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__; +#endif + %extend { + // This will be called through the mp_ass_subscript slot to delete an entry. + void __setitem__(const key_type& key) { + self->erase(key); + } + void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) { self->insert(Type::value_type(key,x)); } diff --git a/Lib/python/std_pair.i b/Lib/python/std_pair.i index da31918c8..172572bff 100644 --- a/Lib/python/std_pair.i +++ b/Lib/python/std_pair.i @@ -31,7 +31,7 @@ int res2 = swig::asval((PyObject*)second, psecond); if (!SWIG_IsOK(res2)) return res2; return res1 > res2 ? res1 : res2; - } + } } static int asval(PyObject *obj, std::pair *val) { @@ -68,10 +68,16 @@ value_type *vp = %new_instance(std::pair); T *pfirst = &(vp->first); int res1 = swig::asval((PyObject*)first, pfirst); - if (!SWIG_IsOK(res1)) return res1; + if (!SWIG_IsOK(res1)) { + %delete(vp); + return res1; + } U *psecond = &(vp->second); int res2 = swig::asval((PyObject*)second, psecond); - if (!SWIG_IsOK(res2)) return res2; + if (!SWIG_IsOK(res2)) { + %delete(vp); + return res2; + } *val = vp; return SWIG_AddNewMask(res1 > res2 ? res1 : res2); } else { @@ -82,7 +88,7 @@ int res2 = swig::asval((PyObject*)second, psecond); if (!SWIG_IsOK(res2)) return res2; return res1 > res2 ? res1 : res2; - } + } } static int asptr(PyObject *obj, std::pair **val) { diff --git a/Lib/python/std_set.i b/Lib/python/std_set.i index 53f97e475..0ef011998 100644 --- a/Lib/python/std_set.i +++ b/Lib/python/std_set.i @@ -36,7 +36,12 @@ %swig_sequence_iterator(set); %swig_container_methods(set); - %extend { +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__; + %feature("python:slot", "sq_contains", functype="objobjproc") __contains__; +#endif + + %extend { void append(value_type x) { self->insert(x); } @@ -56,8 +61,7 @@ void discard(value_type x) { self->erase(x); } - - }; + } %enddef %include diff --git a/Lib/python/std_unordered_map.i b/Lib/python/std_unordered_map.i index 894840c6c..042d5b671 100644 --- a/Lib/python/std_unordered_map.i +++ b/Lib/python/std_unordered_map.i @@ -1,106 +1,16 @@ /* Unordered Maps */ +%include -%fragment("StdMapTraits","header",fragment="StdSequenceTraits") +%fragment("StdUnorderedMapForwardIteratorTraits","header") { namespace swig { - template - inline void - assign(const SwigPySeq& swigpyseq, std::unordered_map *unordered_map) { - typedef typename std::unordered_map::value_type value_type; - typename SwigPySeq::const_iterator it = swigpyseq.begin(); - for (;it != swigpyseq.end(); ++it) { - unordered_map->insert(value_type(it->first, it->second)); - } - } - - template - struct traits_reserve > { - static void reserve(std::unordered_map &seq, typename std::unordered_map::size_type n) { - seq.reserve(n); - } - }; - - template - struct traits_asptr > { - typedef std::unordered_map unordered_map_type; - static int asptr(PyObject *obj, unordered_map_type **val) { - int res = SWIG_ERROR; - if (PyDict_Check(obj)) { - SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL); -%#if PY_VERSION_HEX >= 0x03000000 - /* In Python 3.x the ".items()" method return a dict_items object */ - items = PySequence_Fast(items, ".items() havn't returned a sequence!"); -%#endif - res = traits_asptr_stdseq, std::pair >::asptr(items, val); - } else { - unordered_map_type *p; - swig_type_info *descriptor = swig::type_info(); - res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; - if (SWIG_IsOK(res) && val) *val = p; - } - return res; - } - }; - - template - struct traits_from > { - typedef std::unordered_map unordered_map_type; - typedef typename unordered_map_type::const_iterator const_iterator; - typedef typename unordered_map_type::size_type size_type; - - static PyObject *from(const unordered_map_type& unordered_map) { - swig_type_info *desc = swig::type_info(); - if (desc && desc->clientdata) { - return SWIG_NewPointerObj(new unordered_map_type(unordered_map), desc, SWIG_POINTER_OWN); - } else { - size_type size = unordered_map.size(); - Py_ssize_t pysize = (size <= (size_type) INT_MAX) ? (Py_ssize_t) size : -1; - if (pysize < 0) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(PyExc_OverflowError, "unordered_map size not valid in python"); - SWIG_PYTHON_THREAD_END_BLOCK; - return NULL; - } - PyObject *obj = PyDict_New(); - for (const_iterator i= unordered_map.begin(); i!= unordered_map.end(); ++i) { - swig::SwigVar_PyObject key = swig::from(i->first); - swig::SwigVar_PyObject val = swig::from(i->second); - PyDict_SetItem(obj, key, val); - } - return obj; - } - } - }; - - template - struct from_key_oper - { - typedef const ValueType& argument_type; - typedef PyObject *result_type; - result_type operator()(argument_type v) const - { - return swig::from(v.first); - } - }; - - template - struct from_value_oper - { - typedef const ValueType& argument_type; - typedef PyObject *result_type; - result_type operator()(argument_type v) const - { - return swig::from(v.second); - } - }; - template - struct SwigPyMapIterator_T : SwigPyIteratorClosed_T + struct SwigPyMapForwardIterator_T : SwigPyForwardIteratorClosed_T { - SwigPyMapIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) - : SwigPyIteratorClosed_T(curr, first, last, seq) + SwigPyMapForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) + : SwigPyForwardIteratorClosed_T(curr, first, last, seq) { } }; @@ -108,27 +18,27 @@ template > - struct SwigPyMapKeyIterator_T : SwigPyMapIterator_T + struct SwigPyMapKeyForwardIterator_T : SwigPyMapForwardIterator_T { - SwigPyMapKeyIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) - : SwigPyMapIterator_T(curr, first, last, seq) + SwigPyMapKeyForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) + : SwigPyMapForwardIterator_T(curr, first, last, seq) { } }; template inline SwigPyIterator* - make_output_key_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) + make_output_key_forward_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) { - return new SwigPyMapKeyIterator_T(current, begin, end, seq); + return new SwigPyMapKeyForwardIterator_T(current, begin, end, seq); } template > - struct SwigPyMapValueITerator_T : SwigPyMapIterator_T + struct SwigPyMapValueForwardIterator_T : SwigPyMapForwardIterator_T { - SwigPyMapValueITerator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) - : SwigPyMapIterator_T(curr, first, last, seq) + SwigPyMapValueForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) + : SwigPyMapForwardIterator_T(curr, first, last, seq) { } }; @@ -136,26 +46,143 @@ template inline SwigPyIterator* - make_output_value_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) + make_output_value_forward_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) { - return new SwigPyMapValueITerator_T(current, begin, end, seq); + return new SwigPyMapValueForwardIterator_T(current, begin, end, seq); } } } +%fragment("StdUnorderedMapTraits","header",fragment="StdMapCommonTraits",fragment="StdUnorderedMapForwardIteratorTraits") +{ + namespace swig { + template + inline void + assign(const SwigPySeq& swigpyseq, std::unordered_map *unordered_map) { + typedef typename std::unordered_map::value_type value_type; + typename SwigPySeq::const_iterator it = swigpyseq.begin(); + for (;it != swigpyseq.end(); ++it) { + unordered_map->insert(value_type(it->first, it->second)); + } + } + + template + struct traits_reserve > { + static void reserve(std::unordered_map &seq, typename std::unordered_map::size_type n) { + seq.reserve(n); + } + }; + + template + struct traits_asptr > { + typedef std::unordered_map unordered_map_type; + static int asptr(PyObject *obj, unordered_map_type **val) { + int res = SWIG_ERROR; + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + if (PyDict_Check(obj)) { + SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL); +%#if PY_VERSION_HEX >= 0x03000000 + /* In Python 3.x the ".items()" method returns a dict_items object */ + items = PySequence_Fast(items, ".items() didn't return a sequence!"); +%#endif + res = traits_asptr_stdseq, std::pair >::asptr(items, val); + } else { + unordered_map_type *p; + swig_type_info *descriptor = swig::type_info(); + res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; + if (SWIG_IsOK(res) && val) *val = p; + } + SWIG_PYTHON_THREAD_END_BLOCK; + return res; + } + }; + + template + struct traits_from > { + typedef std::unordered_map unordered_map_type; + typedef typename unordered_map_type::const_iterator const_iterator; + typedef typename unordered_map_type::size_type size_type; + + static PyObject *asdict(const unordered_map_type& map) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + size_type size = map.size(); + Py_ssize_t pysize = (size <= (size_type) INT_MAX) ? (Py_ssize_t) size : -1; + if (pysize < 0) { + PyErr_SetString(PyExc_OverflowError, "map size not valid in python"); + SWIG_PYTHON_THREAD_END_BLOCK; + return NULL; + } + PyObject *obj = PyDict_New(); + for (const_iterator i= map.begin(); i!= map.end(); ++i) { + swig::SwigVar_PyObject key = swig::from(i->first); + swig::SwigVar_PyObject val = swig::from(i->second); + PyDict_SetItem(obj, key, val); + } + SWIG_PYTHON_THREAD_END_BLOCK; + return obj; + } + + static PyObject *from(const unordered_map_type& map) { + swig_type_info *desc = swig::type_info(); + if (desc && desc->clientdata) { + return SWIG_InternalNewPointerObj(new unordered_map_type(map), desc, SWIG_POINTER_OWN); + } else { + return asdict(map); + } + } + }; + } +} + %define %swig_unordered_map_common(Map...) - %swig_sequence_iterator(Map); + %swig_sequence_forward_iterator(Map); %swig_container_methods(Map) +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "mp_length", functype="lenfunc") __len__; + %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__; + %feature("python:slot", "tp_iter", functype="getiterfunc") key_iterator; + %feature("python:slot", "sq_contains", functype="objobjproc") __contains__; + %extend { - mapped_type __getitem__(const key_type& key) const throw (std::out_of_range) { + %newobject iterkeys(PyObject **PYTHON_SELF); + swig::SwigPyIterator* iterkeys(PyObject **PYTHON_SELF) { + return swig::make_output_key_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + } + + %newobject itervalues(PyObject **PYTHON_SELF); + swig::SwigPyIterator* itervalues(PyObject **PYTHON_SELF) { + return swig::make_output_value_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + } + + %newobject iteritems(PyObject **PYTHON_SELF); + swig::SwigPyIterator* iteritems(PyObject **PYTHON_SELF) { + return swig::make_output_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + } + } + +#else + %extend { + %pythoncode %{def __iter__(self): + return self.key_iterator()%} + %pythoncode %{def iterkeys(self): + return self.key_iterator()%} + %pythoncode %{def itervalues(self): + return self.value_iterator()%} + %pythoncode %{def iteritems(self): + return self.iterator()%} + } +#endif + + %extend { + mapped_type const & __getitem__(const key_type& key) throw (std::out_of_range) { Map::const_iterator i = self->find(key); if (i != self->end()) return i->second; else throw std::out_of_range("key not found"); } - + void __delitem__(const key_type& key) throw (std::out_of_range) { Map::iterator i = self->find(key); if (i != self->end()) @@ -172,8 +199,8 @@ PyObject* keys() { Map::size_type size = self->size(); Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1; + SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (pysize < 0) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetString(PyExc_OverflowError, "unordered_map size not valid in python"); SWIG_PYTHON_THREAD_END_BLOCK; return NULL; @@ -183,14 +210,15 @@ for (Py_ssize_t j = 0; j < pysize; ++i, ++j) { PyList_SET_ITEM(keyList, j, swig::from(i->first)); } + SWIG_PYTHON_THREAD_END_BLOCK; return keyList; } PyObject* values() { Map::size_type size = self->size(); Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1; + SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (pysize < 0) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetString(PyExc_OverflowError, "unordered_map size not valid in python"); SWIG_PYTHON_THREAD_END_BLOCK; return NULL; @@ -200,14 +228,15 @@ for (Py_ssize_t j = 0; j < pysize; ++i, ++j) { PyList_SET_ITEM(valList, j, swig::from(i->second)); } + SWIG_PYTHON_THREAD_END_BLOCK; return valList; } PyObject* items() { Map::size_type size = self->size(); Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1; + SWIG_PYTHON_THREAD_BEGIN_BLOCK; if (pysize < 0) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetString(PyExc_OverflowError, "unordered_map size not valid in python"); SWIG_PYTHON_THREAD_END_BLOCK; return NULL; @@ -217,42 +246,50 @@ for (Py_ssize_t j = 0; j < pysize; ++i, ++j) { PyList_SET_ITEM(itemList, j, swig::from(*i)); } + SWIG_PYTHON_THREAD_END_BLOCK; return itemList; } - // Python 2.2 methods bool __contains__(const key_type& key) { return self->find(key) != self->end(); } %newobject key_iterator(PyObject **PYTHON_SELF); swig::SwigPyIterator* key_iterator(PyObject **PYTHON_SELF) { - return swig::make_output_key_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + return swig::make_output_key_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } %newobject value_iterator(PyObject **PYTHON_SELF); swig::SwigPyIterator* value_iterator(PyObject **PYTHON_SELF) { - return swig::make_output_value_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + return swig::make_output_value_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } - - %pythoncode %{def __iter__(self): - return self.key_iterator()%} - %pythoncode %{def iterkeys(self): - return self.key_iterator()%} - %pythoncode %{def itervalues(self): - return self.value_iterator()%} - %pythoncode %{def iteritems(self): - return self.iterator()%} } + %enddef %define %swig_unordered_map_methods(Map...) %swig_unordered_map_common(Map) + +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__; +#endif + %extend { + // This will be called through the mp_ass_subscript slot to delete an entry. + void __setitem__(const key_type& key) { + self->erase(key); + } + void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) { (*self)[key] = x; } + + PyObject* asdict() { + return swig::traits_from< Map >::asdict(*self); + } } + + %enddef diff --git a/Lib/python/std_unordered_multimap.i b/Lib/python/std_unordered_multimap.i index 2410aa52b..281140445 100644 --- a/Lib/python/std_unordered_multimap.i +++ b/Lib/python/std_unordered_multimap.i @@ -3,34 +3,38 @@ */ %include -%fragment("StdUnorderedMultimapTraits","header",fragment="StdSequenceTraits") +%fragment("StdUnorderedMultimapTraits","header",fragment="StdMapCommonTraits",fragment="StdUnorderedMapForwardIteratorTraits") { namespace swig { - template + template inline void - assign(const SwigPySeq& swigpyseq, std::unordered_multimap *unordered_multimap) { - typedef typename std::unordered_multimap::value_type value_type; + assign(const SwigPySeq& swigpyseq, std::unordered_multimap *unordered_multimap) { + typedef typename std::unordered_multimap::value_type value_type; typename SwigPySeq::const_iterator it = swigpyseq.begin(); for (;it != swigpyseq.end(); ++it) { unordered_multimap->insert(value_type(it->first, it->second)); } } - template - struct traits_reserve > { - static void reserve(std::unordered_multimap &seq, typename std::unordered_multimap::size_type n) { + template + struct traits_reserve > { + static void reserve(std::unordered_multimap &seq, typename std::unordered_multimap::size_type n) { seq.reserve(n); } }; - template - struct traits_asptr > { - typedef std::unordered_multimap unordered_multimap_type; - static int asptr(PyObject *obj, std::unordered_multimap **val) { + template + struct traits_asptr > { + typedef std::unordered_multimap unordered_multimap_type; + static int asptr(PyObject *obj, std::unordered_multimap **val) { int res = SWIG_ERROR; if (PyDict_Check(obj)) { SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL); - return traits_asptr_stdseq, std::pair >::asptr(items, val); +%#if PY_VERSION_HEX >= 0x03000000 + /* In Python 3.x the ".items()" method returns a dict_items object */ + items = PySequence_Fast(items, ".items() didn't return a sequence!"); +%#endif + res = traits_asptr_stdseq, std::pair >::asptr(items, val); } else { unordered_multimap_type *p; swig_type_info *descriptor = swig::type_info(); @@ -41,16 +45,16 @@ } }; - template - struct traits_from > { - typedef std::unordered_multimap unordered_multimap_type; + template + struct traits_from > { + typedef std::unordered_multimap unordered_multimap_type; typedef typename unordered_multimap_type::const_iterator const_iterator; typedef typename unordered_multimap_type::size_type size_type; static PyObject *from(const unordered_multimap_type& unordered_multimap) { swig_type_info *desc = swig::type_info(); if (desc && desc->clientdata) { - return SWIG_NewPointerObj(new unordered_multimap_type(unordered_multimap), desc, SWIG_POINTER_OWN); + return SWIG_InternalNewPointerObj(new unordered_multimap_type(unordered_multimap), desc, SWIG_POINTER_OWN); } else { size_type size = unordered_multimap.size(); Py_ssize_t pysize = (size <= (size_type) INT_MAX) ? (Py_ssize_t) size : -1; @@ -74,8 +78,18 @@ } %define %swig_unordered_multimap_methods(Type...) - %swig_map_common(Type); + %swig_unordered_map_common(Type); + +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__; +#endif + %extend { + // This will be called through the mp_ass_subscript slot to delete an entry. + void __setitem__(const key_type& key) { + self->erase(key); + } + void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) { self->insert(Type::value_type(key,x)); } diff --git a/Lib/python/std_unordered_multiset.i b/Lib/python/std_unordered_multiset.i index 0d9f3d9c6..b0f3f096b 100644 --- a/Lib/python/std_unordered_multiset.i +++ b/Lib/python/std_unordered_multiset.i @@ -7,9 +7,9 @@ %fragment("StdUnorderedMultisetTraits","header",fragment="StdSequenceTraits") %{ namespace swig { - template + template inline void - assign(const SwigPySeq& swigpyseq, std::unordered_multiset* seq) { + assign(const SwigPySeq& swigpyseq, std::unordered_multiset* seq) { // seq->insert(swigpyseq.begin(), swigpyseq.end()); // not used as not always implemented typedef typename SwigPySeq::value_type value_type; typename SwigPySeq::const_iterator it = swigpyseq.begin(); @@ -18,30 +18,30 @@ } } - template - struct traits_reserve > { - static void reserve(std::unordered_multiset &seq, typename std::unordered_multiset::size_type n) { + template + struct traits_reserve > { + static void reserve(std::unordered_multiset &seq, typename std::unordered_multiset::size_type n) { seq.reserve(n); } }; - template - struct traits_asptr > { - static int asptr(PyObject *obj, std::unordered_multiset **m) { - return traits_asptr_stdseq >::asptr(obj, m); + template + struct traits_asptr > { + static int asptr(PyObject *obj, std::unordered_multiset **m) { + return traits_asptr_stdseq >::asptr(obj, m); } }; - template - struct traits_from > { - static PyObject *from(const std::unordered_multiset& vec) { - return traits_from_stdseq >::from(vec); + template + struct traits_from > { + static PyObject *from(const std::unordered_multiset& vec) { + return traits_from_stdseq >::from(vec); } }; } %} -#define %swig_unordered_multiset_methods(Set...) %swig_set_methods(Set) +#define %swig_unordered_multiset_methods(Set...) %swig_unordered_set_methods(Set) diff --git a/Lib/python/std_unordered_set.i b/Lib/python/std_unordered_set.i index 855a28da5..79fca6c2f 100644 --- a/Lib/python/std_unordered_set.i +++ b/Lib/python/std_unordered_set.i @@ -5,9 +5,9 @@ %fragment("StdUnorderedSetTraits","header",fragment="StdSequenceTraits") %{ namespace swig { - template + template inline void - assign(const SwigPySeq& swigpyseq, std::unordered_set* seq) { + assign(const SwigPySeq& swigpyseq, std::unordered_set* seq) { // seq->insert(swigpyseq.begin(), swigpyseq.end()); // not used as not always implemented typedef typename SwigPySeq::value_type value_type; typename SwigPySeq::const_iterator it = swigpyseq.begin(); @@ -16,34 +16,40 @@ } } - template - struct traits_reserve > { - static void reserve(std::unordered_set &seq, typename std::unordered_set::size_type n) { + template + struct traits_reserve > { + static void reserve(std::unordered_set &seq, typename std::unordered_set::size_type n) { seq.reserve(n); } }; - template - struct traits_asptr > { - static int asptr(PyObject *obj, std::unordered_set **s) { - return traits_asptr_stdseq >::asptr(obj, s); + template + struct traits_asptr > { + static int asptr(PyObject *obj, std::unordered_set **s) { + return traits_asptr_stdseq >::asptr(obj, s); } }; - template - struct traits_from > { - static PyObject *from(const std::unordered_set& vec) { - return traits_from_stdseq >::from(vec); + template + struct traits_from > { + static PyObject *from(const std::unordered_set& vec) { + return traits_from_stdseq >::from(vec); } }; } %} %define %swig_unordered_set_methods(unordered_set...) - %swig_sequence_iterator(unordered_set); + %swig_sequence_forward_iterator(unordered_set); %swig_container_methods(unordered_set); - %extend { +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "sq_contains", functype="objobjproc") __contains__; + %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__; +#endif + + + %extend { void append(value_type x) { self->insert(x); } @@ -55,8 +61,7 @@ value_type __getitem__(difference_type i) const throw (std::out_of_range) { return *(swig::cgetpos(self, i)); } - - }; + } %enddef %include diff --git a/Lib/python/stl.i b/Lib/python/stl.i index a3566db5c..04f86014f 100644 --- a/Lib/python/stl.i +++ b/Lib/python/stl.i @@ -1,4 +1,7 @@ -/* initial STL definition. extended as needed in each language */ +/* ----------------------------------------------------------------------------- + * stl.i + * ----------------------------------------------------------------------------- */ + %include %include %include diff --git a/Lib/r/boost_shared_ptr.i b/Lib/r/boost_shared_ptr.i index 8ef8d2ef2..668bf4354 100644 --- a/Lib/r/boost_shared_ptr.i +++ b/Lib/r/boost_shared_ptr.i @@ -1,5 +1,11 @@ %include +// Set SHARED_PTR_DISOWN to $disown if required, for example +// #define SHARED_PTR_DISOWN $disown +#if !defined(SHARED_PTR_DISOWN) +#define SHARED_PTR_DISOWN 0 +#endif + // Language specific macro implementing all the customisations for handling the smart pointer %define SWIG_SHARED_PTR_TYPEMAPS(CONST, TYPE...) @@ -8,7 +14,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor wrapper customisation -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -19,7 +25,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); @@ -29,7 +35,8 @@ } } %typemap(out) CONST TYPE { - %set_output(SWIG_NewPointerObj(new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } %typemap(varin) CONST TYPE { @@ -47,16 +54,35 @@ } } %typemap(varout) CONST TYPE { - %set_varoutput(SWIG_NewPointerObj(new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); +} + +%typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) { + int newmem = 0; + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res, "$type"); + } + if (!swig_argp) { + %dirout_nullref("$type"); + } else { + $result = *(%reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get()); + if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); + } } // plain pointer -// Note: $disown not implemented as it will lead to a memory leak of the shared_ptr instance +// Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance %typemap(in) CONST TYPE * (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) { int newmem = 0; - res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -67,8 +93,9 @@ $1 = %const_cast((smartarg ? smartarg->get() : 0), $1_ltype); } } + %typemap(out, fragment="SWIG_null_deleter") CONST TYPE * { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), $owner | SWIG_POINTER_OWN)); } @@ -95,12 +122,20 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE * %{ +#error "directorout typemap for plain pointer not implemented" +%} + // plain reference %typemap(in) CONST TYPE & (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { @@ -140,13 +175,21 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") CONST TYPE & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(&$1 SWIG_NO_NULL_DELETER_0); + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE & %{ +#error "directorout typemap for plain reference not implemented" +%} + // plain pointer by reference -// Note: $disown not implemented as it will lead to a memory leak of the shared_ptr instance +// Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance %typemap(in) TYPE *CONST& (void *argp = 0, int res = 0, $*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { int newmem = 0; - res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -158,7 +201,7 @@ $1 = &temp; } %typemap(out, fragment="SWIG_null_deleter") TYPE *CONST& { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -169,12 +212,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") TYPE *CONST& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) TYPE *CONST& %{ +#error "directorout typemap for plain pointer by reference not implemented" +%} + // shared_ptr by value %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *argp, int res = 0) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) $1 = *(%reinterpret_cast(argp, $<ype)); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $<ype); @@ -199,12 +250,28 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *swig_argp, int swig_res = 0) { + int newmem = 0; + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res, "$type"); + } + if (swig_argp) { + $result = *(%reinterpret_cast(swig_argp, $<ype)); + if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, $<ype); + } +} + // shared_ptr by reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (void *argp, int res = 0, $*1_ltype tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -226,12 +293,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{ +#error "directorout typemap for shared_ptr ref not implemented" +%} + // shared_ptr by pointer %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (void *argp, int res = 0, $*1_ltype tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -242,7 +317,7 @@ } } %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 && *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); if ($owner) delete $1; } @@ -254,12 +329,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{ +#error "directorout typemap for pointer to shared_ptr not implemented" +%} + // shared_ptr by pointer reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (void *argp, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, $*1_ltype temp = 0) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) tempshared = *%reinterpret_cast(argp, $*ltype); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $*ltype); @@ -267,7 +350,7 @@ $1 = &temp; } %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 && **$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -278,10 +361,18 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{ +#error "directorout typemap for pointer ref to shared_ptr not implemented" +%} + // Typecheck typemaps -// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting +// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, @@ -305,5 +396,6 @@ %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; -%enddef + +%enddef diff --git a/Lib/r/r.swg b/Lib/r/r.swg index cf1cfc8f9..8cf8cdf53 100644 --- a/Lib/r/r.swg +++ b/Lib/r/r.swg @@ -3,9 +3,9 @@ %insert("header") "swiglabels.swg" -%insert("header") "swigerrors.swg" %insert("init") "swiginit.swg" %insert("runtime") "swigrun.swg" +%insert("runtime") "swigerrors.swg" %insert("runtime") "rrun.swg" %init %{ @@ -192,6 +192,11 @@ unsigned char *OUTPUT free($1); } +%typemap(in) const enum SWIGTYPE & ($*1_ltype temp) +%{ temp = ($*1_ltype)INTEGER($input)[0]; + $1 = &temp; %} + +%typemap(out) const enum SWIGTYPE & %{ $result = Rf_ScalarInteger((int)*$1); %} %typemap(memberin) char[] %{ if ($input) strcpy($1, $input); diff --git a/Lib/r/ropers.swg b/Lib/r/ropers.swg index c02f7b2f3..acb99798d 100644 --- a/Lib/r/ropers.swg +++ b/Lib/r/ropers.swg @@ -1,43 +1,5 @@ #ifdef __cplusplus -// These are auto-supported by the Perl-module -%rename(__plusplus__) *::operator++; -%rename(__minmin__) *::operator--; -%rename(__add__) *::operator+; -%rename(__sub__) *::operator-; -%rename(__neg__) *::operator-(); -%rename(__neg__) *::operator-() const; -%rename(__mul__) *::operator*; -%rename(__div__) *::operator/; -%rename(__eq__) *::operator==; -%rename(__ne__) *::operator!=; -%rename(__mod__) *::operator%; -%rename(__gt__) *::operator>; -%rename(__lt__) *::operator<; -%rename(__not__) *::operator!; - -// These are renamed, but no 'use overload...' is added -%rename(__lshift__) *::operator<<; -%rename(__rshift__) *::operator>>; -%rename(__and__) *::operator&; -%rename(__or__) *::operator|; -%rename(__xor__) *::operator^; -%rename(__invert__) *::operator~; -%rename(__le__) *::operator<=; -%rename(__ge__) *::operator>=; -%rename(__call__) *::operator(); -%rename(__getitem__) *::operator[]; - -%rename(__seteq__) *::operator=; - - -%rename(__land__) operator&&; -%rename(__lor__) operator||; -%rename(__plusplus__) *::operator++; -%rename(__minusminus__) *::operator--; -%rename(__arrowstar__) *::operator->*; -%rename(__index__) *::operator[]; - %rename(Equal) operator =; %rename(PlusEqual) operator +=; %rename(MinusEqual) operator -=; diff --git a/Lib/r/rrun.swg b/Lib/r/rrun.swg index f2c14a574..c341321a1 100644 --- a/Lib/r/rrun.swg +++ b/Lib/r/rrun.swg @@ -20,6 +20,7 @@ extern "C" { #define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_R_ConvertPtr(obj, pptr, type, flags) #define SWIG_NewPointerObj(ptr, type, flags) SWIG_R_NewPointerObj(ptr, type, flags) +#include #include #include @@ -212,17 +213,15 @@ R_SWIG_ReferenceFinalizer(SEXP el) return; } -typedef enum {R_SWIG_EXTERNAL, R_SWIG_OWNER } R_SWIG_Owner; - SWIGRUNTIME SEXP -SWIG_MakePtr(void *ptr, const char *typeName, R_SWIG_Owner owner) +SWIG_MakePtr(void *ptr, const char *typeName, int flags) { SEXP external, r_obj; Rf_protect(external = R_MakeExternalPtr(ptr, Rf_install(typeName), R_NilValue)); Rf_protect(r_obj = NEW_OBJECT(MAKE_CLASS((char *) typeName))); - if(owner) + if (flags & SWIG_POINTER_OWN) R_RegisterCFinalizer(external, R_SWIG_ReferenceFinalizer); r_obj = SET_SLOT(r_obj, Rf_mkString((char *) "ref"), external); @@ -261,7 +260,11 @@ AddOutputArgToReturn(int pos, SEXP value, const char *name, SEXP output) /* Create a new pointer object */ SWIGRUNTIMEINLINE SEXP SWIG_R_NewPointerObj(void *ptr, swig_type_info *type, int flags) { - SEXP rptr = R_MakeExternalPtr(ptr, + SEXP rptr; + if (!ptr) { + return R_NilValue; + } + rptr = R_MakeExternalPtr(ptr, R_MakeExternalPtr(type, R_NilValue, R_NilValue), R_NilValue); SET_S4_OBJECT(rptr); return rptr; @@ -275,7 +278,7 @@ SWIG_R_ConvertPtr(SEXP obj, void **ptr, swig_type_info *ty, int flags) { if (!obj) return SWIG_ERROR; if (obj == R_NilValue) { if (ptr) *ptr = NULL; - return SWIG_OK; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } vptr = R_ExternalPtrAddr(obj); @@ -349,7 +352,7 @@ SWIG_R_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { return ptr ? RSwigPacked_New((void *) ptr, sz, type) : R_NilValue; } -/* Convert a packed value value */ +/* Convert a packed pointer value */ SWIGRUNTIME int SWIG_R_ConvertPacked(SEXP obj, void *ptr, size_t sz, swig_type_info *ty) { diff --git a/Lib/r/rstdcommon.swg b/Lib/r/rstdcommon.swg index e6c873a07..5f41fd144 100644 --- a/Lib/r/rstdcommon.swg +++ b/Lib/r/rstdcommon.swg @@ -39,7 +39,7 @@ namespace swig { template struct traits_asptr { static int asptr(SWIG_Object obj, Type **val) { - Type *p; + Type *p = 0; swig_type_info *descriptor = type_info(); int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; if (SWIG_IsOK(res)) { @@ -101,12 +101,11 @@ namespace swig { template struct traits_as { - static Type as(SWIG_Object obj, bool throw_error) { + static Type as(SWIG_Object obj) { Type v; int res = asval(obj, &v); if (!obj || !SWIG_IsOK(res)) { - if (throw_error) - throw std::invalid_argument("bad type"); + throw std::invalid_argument("bad type"); } return v; } @@ -114,7 +113,7 @@ namespace swig { template struct traits_as { - static Type as(SWIG_Object obj, bool throw_error) { + static Type as(SWIG_Object obj) { Type *v = 0; int res = (obj ? traits_asptr::asptr(obj, &v) : SWIG_ERROR); if (SWIG_IsOK(res) && v) { @@ -126,12 +125,7 @@ namespace swig { return *v; } } else { - // Uninitialized return value, no Type() constructor required. - static Type *v_def = (Type*) malloc(sizeof(Type)); - if (throw_error) throw std::invalid_argument("bad type"); - memset(v_def,0,sizeof(Type)); - return *v_def; } } }; @@ -152,8 +146,8 @@ namespace swig { }; template - inline Type as(SWIG_Object obj, bool te = false) { - return traits_as::category>::as(obj, te); + inline Type as(SWIG_Object obj) { + return traits_as::category>::as(obj); } template diff --git a/Lib/r/rtype.swg b/Lib/r/rtype.swg index 22639f2d0..bdc48c24e 100644 --- a/Lib/r/rtype.swg +++ b/Lib/r/rtype.swg @@ -16,6 +16,7 @@ %typemap("rtype") enum SWIGTYPE * "character"; %typemap("rtype") enum SWIGTYPE *const "character"; %typemap("rtype") enum SWIGTYPE & "character"; +%typemap("rtype") const enum SWIGTYPE & "character"; %typemap("rtype") enum SWIGTYPE && "character"; %typemap("rtype") SWIGTYPE * "$R_class"; %typemap("rtype") SWIGTYPE *const "$R_class"; @@ -86,9 +87,7 @@ %typemap(scoercein) enum SWIGTYPE %{ $input = enumToInteger($input, "$R_class"); %} %typemap(scoercein) enum SWIGTYPE & - %{ $input = enumToInteger($input, "$R_class"); %} -%typemap(scoercein) enum SWIGTYPE && - %{ $input = enumToInteger($input, "$R_class"); %} + %{ $input = enumToInteger($input, "$*R_class"); %} %typemap(scoercein) enum SWIGTYPE * %{ $input = enumToInteger($input, "$R_class"); %} %typemap(scoercein) enum SWIGTYPE *const @@ -138,7 +137,7 @@ string &, std::string & %{ $result = enumFromInteger($result, "$R_class"); %} %typemap(scoerceout) enum SWIGTYPE & - %{ $result = enumFromInteger($result, "$R_class"); %} + %{ $result = enumFromInteger($result, "$*R_class"); %} %typemap(scoerceout) enum SWIGTYPE && %{ $result = enumFromInteger($result, "$R_class"); %} @@ -152,19 +151,26 @@ string &, std::string & %typemap(scoerceout) SEXP %{ %} %typemap(scoerceout) SWIGTYPE - %{ $result <- new("$&R_class", ref=$result); %} + %{ $result <- if (is.null($result)) $result + else new("$&R_class", ref=$result); %} %typemap(scoerceout) SWIGTYPE & - %{ $result <- new("$R_class", ref=$result) ; %} + %{ $result <- if (is.null($result)) $result + else new("$R_class", ref=$result); %} + %typemap(scoerceout) SWIGTYPE && - %{ $result <- new("$R_class", ref=$result) ; %} + %{ $result <- if (is.null($result)) $result + else new("$R_class", ref=$result); %} %typemap(scoerceout) SWIGTYPE * - %{ $result <- new("$R_class", ref=$result) ; %} + %{ $result <- if (is.null($result)) $result + else new("$R_class", ref=$result); %} + %typemap(scoerceout) SWIGTYPE *const - %{ $result <- new("$R_class", ref=$result) ; %} + %{ $result <- if (is.null($result)) $result + else new("$R_class", ref=$result); %} /* Override the SWIGTYPE * above. */ diff --git a/Lib/r/srun.swg b/Lib/r/srun.swg index 2045ab94e..2e8eda112 100644 --- a/Lib/r/srun.swg +++ b/Lib/r/srun.swg @@ -7,7 +7,7 @@ # This could be provided as a separate run-time library but this -# approach allows the code to to be included directly into the +# approach allows the code to be included directly into the # generated bindings and so removes the need to have and install an # additional library. We may however end up with multiple copies of # this and some confusion at run-time as to which class to use. This @@ -73,7 +73,7 @@ function(name, .values, where = topenv(parent.frame()), suffix = "Value") { # Mirror the class definitions via the E analogous to .__C__ defName = paste(".__E__", name, sep = "") - assign(defName, .values, envir = where) + delayedAssign(defName, .values, assign.env = where) if(nchar(suffix)) name = paste(name, suffix, sep = "") diff --git a/Lib/r/std_shared_ptr.i b/Lib/r/std_shared_ptr.i new file mode 100644 index 000000000..df873679c --- /dev/null +++ b/Lib/r/std_shared_ptr.i @@ -0,0 +1,2 @@ +#define SWIG_SHARED_PTR_NAMESPACE std +%include diff --git a/Lib/r/stl.i b/Lib/r/stl.i index 37e2ccbf4..91da6a2bf 100644 --- a/Lib/r/stl.i +++ b/Lib/r/stl.i @@ -1,10 +1,9 @@ -/* initial STL definition. extended as needed in each language */ -%include std_common.i -%include std_vector.i -%include std_pair.i -%include std_string.i - - - +/* ----------------------------------------------------------------------------- + * stl.i + * ----------------------------------------------------------------------------- */ +%include +%include +%include +%include diff --git a/Lib/ruby/boost_shared_ptr.i b/Lib/ruby/boost_shared_ptr.i index 938074d81..9676bf9d8 100644 --- a/Lib/ruby/boost_shared_ptr.i +++ b/Lib/ruby/boost_shared_ptr.i @@ -6,10 +6,6 @@ #define SHARED_PTR_DISOWN 0 #endif -%fragment("SWIG_null_deleter_python", "header", fragment="SWIG_null_deleter") { -%#define SWIG_NO_NULL_DELETER_SWIG_BUILTIN_INIT -} - // Language specific macro implementing all the customisations for handling the smart pointer %define SWIG_SHARED_PTR_TYPEMAPS(CONST, TYPE...) @@ -62,6 +58,24 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) { + swig_ruby_owntype newmem = {0, 0}; + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res, "$type"); + } + if (!swig_argp) { + %dirout_nullref("$type"); + } else { + $result = *(%reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get()); + if (newmem.own & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); + } +} + // plain pointer // Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance %typemap(in) CONST TYPE * (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) { @@ -80,7 +94,7 @@ } } -%typemap(out, fragment="SWIG_null_deleter_python") CONST TYPE * { +%typemap(out, fragment="SWIG_null_deleter") CONST TYPE * { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), $owner | SWIG_POINTER_OWN)); } @@ -103,11 +117,19 @@ $1 = %const_cast((smartarg ? smartarg->get() : 0), $1_ltype); } } -%typemap(varout, fragment="SWIG_null_deleter_python") CONST TYPE * { +%typemap(varout, fragment="SWIG_null_deleter") CONST TYPE * { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE * %{ +#error "directorout typemap for plain pointer not implemented" +%} + // plain reference %typemap(in) CONST TYPE & (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { swig_ruby_owntype newmem = {0, 0}; @@ -124,7 +146,7 @@ $1 = %const_cast(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get(), $1_ltype); } } -%typemap(out, fragment="SWIG_null_deleter_python") CONST TYPE & { +%typemap(out, fragment="SWIG_null_deleter") CONST TYPE & { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner); %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -148,11 +170,19 @@ $1 = *%const_cast(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get(), $1_ltype); } } -%typemap(varout, fragment="SWIG_null_deleter_python") CONST TYPE & { +%typemap(varout, fragment="SWIG_null_deleter") CONST TYPE & { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(&$1 SWIG_NO_NULL_DELETER_0); %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") CONST TYPE & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(&$1 SWIG_NO_NULL_DELETER_0); + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE & %{ +#error "directorout typemap for plain reference not implemented" +%} + // plain pointer by reference // Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance %typemap(in) TYPE *CONST& (void *argp = 0, int res = 0, $*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { @@ -170,8 +200,8 @@ } $1 = &temp; } -%typemap(out, fragment="SWIG_null_deleter_python") TYPE *CONST& { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner); +%typemap(out, fragment="SWIG_null_deleter") TYPE *CONST& { + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -182,6 +212,14 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") TYPE *CONST& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) TYPE *CONST& %{ +#error "directorout typemap for plain pointer by reference not implemented" +%} + // shared_ptr by value %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *argp, int res = 0) { swig_ruby_owntype newmem = {0, 0}; @@ -212,6 +250,22 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *swig_argp, int swig_res = 0) { + swig_ruby_owntype newmem = {0, 0}; + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res, "$type"); + } + if (swig_argp) { + $result = *(%reinterpret_cast(swig_argp, $<ype)); + if (newmem.own & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, $<ype); + } +} + // shared_ptr by reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (void *argp, int res = 0, $*1_ltype tempshared) { swig_ruby_owntype newmem = {0, 0}; @@ -239,6 +293,14 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{ +#error "directorout typemap for shared_ptr ref not implemented" +%} + // shared_ptr by pointer %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (void *argp, int res = 0, $*1_ltype tempshared) { swig_ruby_owntype newmem = {0, 0}; @@ -255,7 +317,7 @@ } } %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 && *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); if ($owner) delete $1; } @@ -267,6 +329,14 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{ +#error "directorout typemap for pointer to shared_ptr not implemented" +%} + // shared_ptr by pointer reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (void *argp, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, $*1_ltype temp = 0) { swig_ruby_owntype newmem = {0, 0}; @@ -280,7 +350,7 @@ $1 = &temp; } %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 && **$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -291,10 +361,18 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{ +#error "directorout typemap for pointer ref to shared_ptr not implemented" +%} + // Typecheck typemaps // Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, diff --git a/Lib/ruby/cni.i b/Lib/ruby/cni.i deleted file mode 100644 index 10a1403a2..000000000 --- a/Lib/ruby/cni.i +++ /dev/null @@ -1,2 +0,0 @@ -%include -%include diff --git a/Lib/ruby/director.swg b/Lib/ruby/director.swg index c6c53a343..9395b8183 100644 --- a/Lib/ruby/director.swg +++ b/Lib/ruby/director.swg @@ -153,43 +153,6 @@ namespace Swig { } }; - /* unknown exception handler */ - class UnknownExceptionHandler { -#ifdef SWIG_DIRECTOR_UEH - static void handler() { - try { - throw; - } catch (DirectorException& e) { - std::cerr << "SWIG Director exception caught:" << std::endl - << e.what() << std::endl; - } catch (std::exception& e) { - std::cerr << "std::exception caught: "<< e.what() << std::endl; - } catch (...) { - std::cerr << "Unknown exception caught." << std::endl; - } - std::cerr << std::endl - << "Ruby interpreter traceback:" << std::endl; - std::cerr << std::endl; - std::cerr << "This exception was caught by the SWIG unexpected exception handler." << std::endl - << "Try using %feature(\"director:except\") to avoid reaching this point." << std::endl - << std::endl - << "Exception is being re-thrown, program will like abort/terminate." << std::endl; - throw; - } - - public: - std::unexpected_handler old; - UnknownExceptionHandler(std::unexpected_handler nh = handler) { - old = std::set_unexpected(nh); - } - - ~UnknownExceptionHandler() { - std::set_unexpected(old); - } -#endif - }; - - /* Type mismatch in the return value from a Ruby method call */ class DirectorTypeMismatchException : public DirectorException { public: diff --git a/Lib/ruby/jstring.i b/Lib/ruby/jstring.i deleted file mode 100644 index 17efa978d..000000000 --- a/Lib/ruby/jstring.i +++ /dev/null @@ -1,44 +0,0 @@ -%include - -%fragment(SWIG_AsVal_frag(jstring),"header") { -SWIGINTERN int -SWIG_AsVal(jstring)(VALUE obj, jstring *val) -{ - if (NIL_P(obj)){ - if (val) *val = 0; - return SWIG_OK; - } - if (TYPE(obj) == T_STRING) { - if (val) { - char *cstr = rb_string_value_ptr(&(obj)); - jsize len = RSTRING_LEN(obj); - *val = JvNewStringLatin1(cstr, len); - } - return SWIG_NEWOBJ; - } - return SWIG_TypeError; -} -} - -%fragment(SWIG_From_frag(jstring),"header") { -SWIGINTERNINLINE VALUE -SWIG_From(jstring)(jstring val) -{ - if (!val) { - return Qnil; - } else { - jint len = JvGetStringUTFLength(val); - char buf[len]; - JvGetStringUTFRegion(val, 0, len, buf); - return rb_str_new(buf,len); - } -} -} - -%typemaps_asvalfrom(%checkcode(STRING), - %arg(SWIG_AsVal(jstring)), - %arg(SWIG_From(jstring)), - %arg(SWIG_AsVal_frag(jstring)), - %arg(SWIG_From_frag(jstring)), - java::lang::String *); - diff --git a/Lib/ruby/ruby.swg b/Lib/ruby/ruby.swg index efa8ec2f7..d1335974e 100644 --- a/Lib/ruby/ruby.swg +++ b/Lib/ruby/ruby.swg @@ -14,7 +14,7 @@ /* Constants created by %constant or #define are UPPER_CASE */ %rename("%(uppercase)s", %$isconstant) ""; -/* SWIG only considers static class members with inline intializers +/* SWIG only considers static class members with inline initializers to be constants. For examples of what is and isn't considered a constant by SWIG see naming.i in the Ruby test suite. */ %rename("%(uppercase)s", %$ismember, %$isvariable,%$isimmutable,%$isstatic,%$hasvalue,%$hasconsttype) ""; diff --git a/Lib/ruby/rubycontainer.swg b/Lib/ruby/rubycontainer.swg index a6d8a59ef..e8830a715 100644 --- a/Lib/ruby/rubycontainer.swg +++ b/Lib/ruby/rubycontainer.swg @@ -38,7 +38,7 @@ namespace swig { template < class T > - struct yield : public std::unary_function< T, bool > + struct yield { bool operator()( const T& v ) const @@ -183,8 +183,8 @@ namespace swig { VALUE item = rb_ary_entry(_seq, _index ); try { - return swig::as(item, true); - } catch (std::exception& e) { + return swig::as(item); + } catch (const std::invalid_argument& e) { char msg[1024]; sprintf(msg, "in sequence element %d ", _index); VALUE lastErr = rb_gv_get("$!"); @@ -926,7 +926,7 @@ namespace swig VALUE elem = argv[0]; int idx = 0; try { - Sequence::value_type val = swig::as( elem, true ); + Sequence::value_type val = swig::as( elem ); if ( i >= len ) { $self->resize(i-1, val); return $self; @@ -943,7 +943,7 @@ namespace swig } } - catch( std::invalid_argument ) + catch(const std::invalid_argument &) { rb_raise( rb_eArgError, "%s", Ruby_Format_TypeError( "", @@ -967,10 +967,10 @@ namespace swig Sequence::iterator start = $self->begin(); VALUE elem = argv[idx]; try { - Sequence::value_type val = swig::as( elem, true ); + Sequence::value_type val = swig::as( elem ); $self->insert( start, val ); } - catch( std::invalid_argument ) + catch(const std::invalid_argument &) { rb_raise( rb_eArgError, "%s", Ruby_Format_TypeError( "", diff --git a/Lib/ruby/rubycontainer_extended.swg b/Lib/ruby/rubycontainer_extended.swg index 7514ba2c8..663dddb8c 100644 --- a/Lib/ruby/rubycontainer_extended.swg +++ b/Lib/ruby/rubycontainer_extended.swg @@ -69,7 +69,7 @@ *i = swig::as< Type >( r ); } } - catch ( const std::invalid_argument& ) + catch (const std::invalid_argument&) { rb_raise(rb_eTypeError, "Yield block did not return a valid element for " "Container"); diff --git a/Lib/ruby/rubyhead.swg b/Lib/ruby/rubyhead.swg index 9960087c6..90f07cf68 100644 --- a/Lib/ruby/rubyhead.swg +++ b/Lib/ruby/rubyhead.swg @@ -91,6 +91,9 @@ #ifndef RSTRUCT_PTR # define RSTRUCT_PTR(x) RSTRUCT(x)->ptr #endif +#ifndef RTYPEDDATA_P +# define RTYPEDDATA_P(x) (TYPE(x) != T_DATA) +#endif diff --git a/Lib/ruby/rubyiterators.swg b/Lib/ruby/rubyiterators.swg index 88f1e7c8c..89fea4527 100644 --- a/Lib/ruby/rubyiterators.swg +++ b/Lib/ruby/rubyiterators.swg @@ -3,7 +3,7 @@ * * Implement a C++ 'output' iterator for Ruby. * - * Users can derive form the Iterator to implemet their + * Users can derive form the Iterator to implement their * own iterators. As an example (real one since we use it for STL/STD * containers), the template Iterator_T does the * implementation for generic C++ iterators. diff --git a/Lib/ruby/rubyrun.swg b/Lib/ruby/rubyrun.swg index 249494ab0..4b2ffe4b4 100644 --- a/Lib/ruby/rubyrun.swg +++ b/Lib/ruby/rubyrun.swg @@ -171,10 +171,11 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags) swig_class *sklass; VALUE klass; VALUE obj; - + if (!ptr) return Qnil; - + + assert(type); if (type->clientdata) { sklass = (swig_class *) type->clientdata; @@ -182,7 +183,7 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags) track = sklass->trackObjects; if (track) { obj = SWIG_RubyInstanceFor(ptr); - + /* Check the object's type and make sure it has the correct type. It might not in cases where methods do things like downcast methods. */ @@ -214,7 +215,7 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags) obj = Data_Wrap_Struct(klass, 0, 0, ptr); } rb_iv_set(obj, "@__swigtype__", rb_str_new2(type->name)); - + return obj; } @@ -246,7 +247,7 @@ typedef struct { SWIGRUNTIME swig_ruby_owntype SWIG_Ruby_AcquirePtr(VALUE obj, swig_ruby_owntype own) { swig_ruby_owntype oldown = {0, 0}; - if (obj) { + if (TYPE(obj) == T_DATA && !RTYPEDDATA_P(obj)) { oldown.datafree = RDATA(obj)->dfree; RDATA(obj)->dfree = own.datafree; } @@ -265,9 +266,9 @@ SWIG_Ruby_ConvertPtrAndOwn(VALUE obj, void **ptr, swig_type_info *ty, int flags, if (NIL_P(obj)) { if (ptr) *ptr = 0; - return SWIG_OK; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } else { - if (TYPE(obj) != T_DATA) { + if (TYPE(obj) != T_DATA || (TYPE(obj) == T_DATA && RTYPEDDATA_P(obj))) { return SWIG_ERROR; } Data_Get_Struct(obj, void, vptr); @@ -362,7 +363,7 @@ SWIG_Ruby_NewPackedObj(void *ptr, int sz, swig_type_info *type) { return rb_str_new2(result); } -/* Convert a packed value value */ +/* Convert a packed pointer value */ SWIGRUNTIME int SWIG_Ruby_ConvertPacked(VALUE obj, void *ptr, int sz, swig_type_info *ty) { swig_cast_info *tc; diff --git a/Lib/ruby/rubystdcommon.swg b/Lib/ruby/rubystdcommon.swg index f72745b56..99dd7f81e 100644 --- a/Lib/ruby/rubystdcommon.swg +++ b/Lib/ruby/rubystdcommon.swg @@ -3,8 +3,9 @@ * The Ruby classes, for C++ * ------------------------------------------------------------ */ %include +%include -%fragment("StdTraits","header",fragment="StdTraitsCommon") +%fragment("StdTraits","header",fragment="StdTraitsCommon",fragment="StdTraitsForwardDeclaration") { namespace swig { @@ -52,7 +53,7 @@ namespace swig { template struct traits_asptr { static int asptr(VALUE obj, Type **val) { - Type *p; + Type *p = 0; swig_type_info *descriptor = type_info(); int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; if (SWIG_IsOK(res)) { @@ -114,15 +115,15 @@ namespace swig { template struct traits_as { - static Type as(VALUE obj, bool throw_error) { + static Type as(VALUE obj) { Type v; int res = asval(obj, &v); - if (!obj || !SWIG_IsOK(res)) { - if (throw_error) throw std::invalid_argument("bad type"); + if (!SWIG_IsOK(res)) { VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) { %type_error(swig::type_name()); } + throw std::invalid_argument("bad type"); } return v; } @@ -130,9 +131,9 @@ namespace swig { template struct traits_as { - static Type as(VALUE obj, bool throw_error) { + static Type as(VALUE obj) { Type *v = 0; - int res = (obj ? traits_asptr::asptr(obj, &v) : SWIG_ERROR); + int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res) && v) { if (SWIG_IsNewObj(res)) { Type r(*v); @@ -142,46 +143,41 @@ namespace swig { return *v; } } else { - // Uninitialized return value, no Type() constructor required. - if (throw_error) throw std::invalid_argument("bad type"); VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) { %type_error(swig::type_name()); } - static Type *v_def = (Type*) malloc(sizeof(Type)); - memset(v_def,0,sizeof(Type)); - return *v_def; + throw std::invalid_argument("bad type"); } } }; template struct traits_as { - static Type* as(VALUE obj, bool throw_error) { + static Type* as(VALUE obj) { Type *v = 0; - int res = (obj ? traits_asptr::asptr(obj, &v) : SWIG_ERROR); + int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res)) { return v; } else { - if (throw_error) throw std::invalid_argument("bad type"); VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) { %type_error(swig::type_name()); } - return 0; + throw std::invalid_argument("bad type"); } } }; template - inline Type as(VALUE obj, bool te = false) { - return traits_as< Type, typename traits< Type >::category >::as(obj, te); + inline Type as(VALUE obj) { + return traits_as< Type, typename traits< Type >::category >::as(obj); } template struct traits_check { static bool check(VALUE obj) { - int res = obj ? asval(obj, (Type *)(0)) : SWIG_ERROR; + int res = asval(obj, (Type *)(0)); return SWIG_IsOK(res) ? true : false; } }; @@ -189,7 +185,7 @@ namespace swig { template struct traits_check { static bool check(VALUE obj) { - int res = obj ? asptr(obj, (Type **)(0)) : SWIG_ERROR; + int res = asptr(obj, (Type **)(0)); return SWIG_IsOK(res) ? true : false; } }; diff --git a/Lib/ruby/rubystdcommon_forward.swg b/Lib/ruby/rubystdcommon_forward.swg new file mode 100644 index 000000000..4120b38e4 --- /dev/null +++ b/Lib/ruby/rubystdcommon_forward.swg @@ -0,0 +1,15 @@ +%fragment("StdTraitsForwardDeclaration","header") +{ +namespace swig { + template struct traits_asptr; + template struct traits_asval; + struct pointer_category; + template struct traits_as; + template struct traits_from; + template struct traits_from_ptr; + template struct noconst_traits; + template swig_type_info* type_info(); + template const char* type_name(); + template VALUE from(const Type& val); +} +} diff --git a/Lib/ruby/rubystdfunctors.swg b/Lib/ruby/rubystdfunctors.swg index f2050b6f2..5150333cd 100644 --- a/Lib/ruby/rubystdfunctors.swg +++ b/Lib/ruby/rubystdfunctors.swg @@ -90,7 +90,7 @@ namespace swig { static ID call_id = rb_intern("call"); template > - struct BinaryPredicate : GC_VALUE, std::binary_function< _T, _T, bool > + struct BinaryPredicate : GC_VALUE { BinaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { } bool operator()(_T a, _T b) const @@ -109,7 +109,7 @@ namespace swig { }; template > - struct BinaryFunction : GC_VALUE, std::binary_function< _T, _T, _T > + struct BinaryFunction : GC_VALUE { BinaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { } _T operator()(_T a, _T b) const @@ -128,7 +128,7 @@ namespace swig { }; template< class _T = GC_VALUE > - struct UnaryPredicate : GC_VALUE, std::unary_function< _T, bool > + struct UnaryPredicate : GC_VALUE { UnaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { } bool operator()(_T a) const @@ -142,7 +142,7 @@ namespace swig { }; template< class _T = GC_VALUE > - struct UnaryFunction : GC_VALUE, std::unary_function< _T, _T > + struct UnaryFunction : GC_VALUE { UnaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { } _T operator()(_T a) const diff --git a/Lib/ruby/rubytracking.swg b/Lib/ruby/rubytracking.swg index 8f9f01be8..b9fb249d8 100644 --- a/Lib/ruby/rubytracking.swg +++ b/Lib/ruby/rubytracking.swg @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- * rubytracking.swg * - * This file contains support for tracking mappings from + * This file contains support for tracking mappings from * Ruby objects to C++ objects. This functionality is needed * to implement mark functions for Ruby's mark and sweep * garbage collector. @@ -28,7 +28,7 @@ extern "C" { #endif /* Global hash table to store Trackings from C/C++ - structs to Ruby Objects. + structs to Ruby Objects. */ static st_table* swig_ruby_trackings = NULL; @@ -42,7 +42,7 @@ SWIGRUNTIME void SWIG_RubyInitializeTrackings(void) { /* Create a hash table to store Trackings from C++ objects to Ruby objects. */ - /* Try to see if some other .so has already created a + /* Try to see if some other .so has already created a tracking hash table, which we keep hidden in an instance var in the SWIG module. This is done to allow multiple DSOs to share the same @@ -101,13 +101,14 @@ SWIGRUNTIME void SWIG_RubyRemoveTracking(void* ptr) { /* This is a helper method that unlinks a Ruby object from its underlying C++ object. This is needed if the lifetime of the - Ruby object is longer than the C++ object */ + Ruby object is longer than the C++ object. */ SWIGRUNTIME void SWIG_RubyUnlinkObjects(void* ptr) { VALUE object = SWIG_RubyInstanceFor(ptr); if (object != Qnil) { - if (TYPE(object) != T_DATA) - abort(); + // object might have the T_ZOMBIE type, but that's just + // because the GC has flagged it as such for a deferred + // destruction. Until then, it's still a T_DATA object. DATA_PTR(object) = 0; } } diff --git a/Lib/ruby/rubyuserdir.swg b/Lib/ruby/rubyuserdir.swg index 638433c2d..1689c7f0d 100644 --- a/Lib/ruby/rubyuserdir.swg +++ b/Lib/ruby/rubyuserdir.swg @@ -11,7 +11,7 @@ /* ------------------------------------------------------------------------- */ /* - Enable keywords paramaters + Enable keywords parameters */ #define %kwargs %feature("kwargs") diff --git a/Lib/ruby/rubywstrings.swg b/Lib/ruby/rubywstrings.swg index b6dd937a5..7da6f4bf2 100644 --- a/Lib/ruby/rubywstrings.swg +++ b/Lib/ruby/rubywstrings.swg @@ -1,71 +1,57 @@ /* ----------------------------------------------------------------------------- * rubywstrings.swg * - * Currently, Ruby does not support Unicode or WChar properly, so these - * are still treated as char arrays for now. - * There are other libraries available that add support to this in - * ruby including WString, FXString, etc. - * ----------------------------------------------------------------------------- */ - -/* ------------------------------------------------------------ * utility methods for wchar_t strings * ------------------------------------------------------------ */ -%fragment("SWIG_AsWCharPtrAndSize","header",fragment="",fragment="SWIG_pwchar_descriptor",fragment="SWIG_AsCharPtrAndSize") { +%fragment("SWIG_AsWCharPtrAndSize","header",fragment="",fragment="SWIG_pwchar_descriptor",fragment="SWIG_AsCharPtrAndSize",fragment="SWIG_ruby_wstring_encoding_init") { SWIGINTERN int SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) { - return SWIG_AsCharPtrAndSize( obj, (char**)cptr, psize, alloc); -// VALUE tmp = 0; -// bool ok = false; -// if ( TYPE(obj) == T_STRING ) { -// if (cptr) { -// obj = tmp = SWIG_Unicode_FromObject(obj); -// ok = true; -// } -// } -// if (ok) { -// Py_ssize_t len = PyUnicode_GetSize(obj); -// rb_notimplement(); -// if (cptr) { -// *cptr = %new_array(len + 1, wchar_t); -// SWIG_Unicode_AsWideChar((PyUnicodeObject *)obj, *cptr, len); -// (*cptr)[len] = 0; -// } -// if (psize) *psize = (size_t) len + 1; -// if (alloc) *alloc = cptr ? SWIG_NEWOBJ : 0; -// return SWIG_OK; -// } else { -// swig_type_info* pwchar_descriptor = SWIG_pwchar_descriptor(); -// if (pwchar_descriptor) { -// void * vptr = 0; -// if (SWIG_ConvertPtr(obj, &vptr, pwchar_descriptor, 0) == SWIG_OK) { -// if (cptr) *cptr = (wchar_t *)vptr; -// if (psize) *psize = vptr ? (wcslen((wchar_t *)vptr) + 1) : 0; -// return SWIG_OK; -// } -// } -// } -// return SWIG_TypeError; + rb_encoding* wstr_enc = swig_ruby_wstring_encoding; + + if (TYPE(obj) == T_STRING) { + VALUE rstr = rb_str_conv_enc(obj, rb_enc_get(obj), wstr_enc); + wchar_t* cstr = (wchar_t*) StringValuePtr(rstr); + size_t size = RSTRING_LEN(rstr) / sizeof(wchar_t) + 1; + + if ( RSTRING_LEN(rstr) % sizeof(wchar_t) != 0 ) { + rb_raise(rb_eRuntimeError, + "The length of the byte sequence of converted string is not a multiplier of sizeof(wchar_t). Invalid byte sequence is given. Or invalid SWIG_RUBY_WSTRING_ENCODING is given when compiling this binding."); + } + if (cptr && alloc) { + *alloc = SWIG_NEWOBJ; + *cptr = %new_array(size, wchar_t); + memmove(*cptr, cstr, RSTRING_LEN(rstr)); + } + if (psize) *psize = size; + + return SWIG_OK; + } else { + return SWIG_TypeError; + } } } -%fragment("SWIG_FromWCharPtrAndSize","header",fragment="",fragment="SWIG_pwchar_descriptor",fragment="SWIG_FromCharPtrAndSize") { +%fragment("SWIG_FromWCharPtrAndSize","header",fragment="",fragment="SWIG_pwchar_descriptor",fragment="SWIG_FromCharPtrAndSize",fragment="SWIG_ruby_wstring_encoding_init") { SWIGINTERNINLINE VALUE SWIG_FromWCharPtrAndSize(const wchar_t * carray, size_t size) { - return SWIG_FromCharPtrAndSize( (const char*)carray, size); -// if (carray) { -// if (size > INT_MAX) { -// swig_type_info* pwchar_descriptor = SWIG_pwchar_descriptor(); -// return pwchar_descriptor ? -// SWIG_NewPointerObj(%const_cast(carray,wchar_t *), pwchar_descriptor, 0) : Qnil; -// } else { -// return SWIG_Unicode_FromWideChar(carray, %numeric_cast(size,int)); -// } -// } else { -// return Qnil; -// } + rb_encoding* wstr_enc = swig_ruby_wstring_encoding; + rb_encoding* rb_enc = swig_ruby_internal_encoding; + + if (carray && size <= LONG_MAX/sizeof(wchar_t)) { + VALUE rstr = rb_str_new( (const char*)carray, %numeric_cast(size*sizeof(wchar_t),long) ); + rb_encoding* new_enc = rb_default_internal_encoding(); + + rb_enc_associate(rstr, wstr_enc); + if ( !new_enc ) { + new_enc = rb_enc; + } + return rb_str_conv_enc(rstr, wstr_enc, new_enc); + } else { + return Qnil; + } } } diff --git a/Lib/ruby/std_basic_string.i b/Lib/ruby/std_basic_string.i index 1351177fc..ba13ba764 100644 --- a/Lib/ruby/std_basic_string.i +++ b/Lib/ruby/std_basic_string.i @@ -13,40 +13,37 @@ %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsCharPtrAndSize") { SWIGINTERN int -SWIG_AsPtr(std::basic_string)(VALUE obj, std::string **val) -{ - static swig_type_info* string_info = - SWIG_TypeQuery("std::basic_string *"); - std::string *vptr; - if (SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0) == SWIG_OK) { +SWIG_AsPtr(std::basic_string)(VALUE obj, std::string **val) { + static swig_type_info* string_info = SWIG_TypeQuery("std::basic_string *"); + std::string *vptr; + if (SWIG_IsOK(SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0))) { if (val) *val = vptr; return SWIG_OLDOBJ; } else { char* buf = 0 ; size_t size = 0; int alloc = 0; - if (SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc) == SWIG_OK) { + if (SWIG_IsOK(SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc))) { if (buf) { if (val) *val = new std::string(buf, size - 1); if (alloc == SWIG_NEWOBJ) %delete_array(buf); return SWIG_NEWOBJ; } } - if (val) { - rb_raise( rb_eTypeError, "a string is expected"); - } - return 0; + return SWIG_ERROR; } -} +} } %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromCharPtrAndSize") { SWIGINTERNINLINE VALUE - SWIG_From(std::basic_string)(const std::string& s) - { + SWIG_From(std::basic_string)(const std::string& s) { return SWIG_FromCharPtrAndSize(s.data(), s.size()); } } +%ignore std::basic_string::operator!=; +%ignore std::basic_string::operator+=; + %include %typemaps_asptrfromn(%checkcode(STRING), std::basic_string); @@ -55,39 +52,37 @@ SWIGINTERNINLINE VALUE #if !defined(SWIG_STD_WSTRING) +%traits_swigtype(std::basic_string); +%fragment(SWIG_Traits_frag(std::basic_string)); + + %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsWCharPtrAndSize") { SWIGINTERN int - SWIG_AsPtr(std::basic_string)(VALUE obj, std::wstring **val) - { - static swig_type_info* string_info = - SWIG_TypeQuery("std::basic_string *"); - std::wstring *vptr; - if (SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0) == SWIG_OK) { - if (val) *val = vptr; - return SWIG_OLDOBJ; - } else { - wchar_t *buf = 0 ; size_t size = 0; int alloc = 0; - if (SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc) == SWIG_OK) { - if (buf) { - if (val) *val = new std::wstring(buf, size - 1); - if (alloc == SWIG_NEWOBJ) %delete_array(buf); - return SWIG_NEWOBJ; - } +SWIG_AsPtr(std::basic_string)(VALUE obj, std::wstring **val) { + static swig_type_info* string_info = SWIG_TypeQuery("std::basic_string *"); + std::wstring *vptr; + if (SWIG_IsOK(SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0))) { + if (val) *val = vptr; + return SWIG_OLDOBJ; + } else { + wchar_t *buf = 0 ; size_t size = 0; int alloc = 0; + if (SWIG_IsOK(SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc))) { + if (buf) { + if (val) *val = new std::wstring(buf, size - 1); + if (alloc == SWIG_NEWOBJ) %delete_array(buf); + return SWIG_NEWOBJ; } - if (val) { - rb_raise( rb_eTypeError, "a string is expected"); - } - return 0; } + return SWIG_ERROR; } } +} %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromWCharPtrAndSize") { SWIGINTERNINLINE VALUE - SWIG_From(std::basic_string)(const std::wstring& s) - { + SWIG_From(std::basic_string)(const std::wstring& s) { return SWIG_FromWCharPtrAndSize(s.data(), s.size()); } } diff --git a/Lib/ruby/std_complex.i b/Lib/ruby/std_complex.i index dacbea2bb..ef4e8a104 100644 --- a/Lib/ruby/std_complex.i +++ b/Lib/ruby/std_complex.i @@ -8,6 +8,13 @@ #include %} +namespace std { + %naturalvar complex; + template class complex; + %template() complex; + %template() complex; +} + /* defining the complex as/from converters */ %swig_cplxdbl_convn(std::complex, std::complex, std::real, std::imag) diff --git a/Lib/ruby/std_deque.i b/Lib/ruby/std_deque.i index 38048aff7..b70f34ee3 100644 --- a/Lib/ruby/std_deque.i +++ b/Lib/ruby/std_deque.i @@ -14,7 +14,7 @@ template struct traits_from > { - static VALUE from(const std::deque & vec) { + static VALUE from(const std::deque& vec) { return traits_from_stdseq >::from(vec); } }; diff --git a/Lib/ruby/std_list.i b/Lib/ruby/std_list.i index 8d4284bbc..b0b4928e4 100644 --- a/Lib/ruby/std_list.i +++ b/Lib/ruby/std_list.i @@ -14,7 +14,7 @@ template struct traits_from > { - static VALUE from(const std::list & vec) { + static VALUE from(const std::list& vec) { return traits_from_stdseq >::from(vec); } }; @@ -27,6 +27,7 @@ #define %swig_list_methods(Type...) %swig_sequence_methods(Type) #define %swig_list_methods_val(Type...) %swig_sequence_methods_val(Type); +%mixin std::list "Enumerable"; %rename("delete") std::list::__delete__; %rename("reject!") std::list::reject_bang; diff --git a/Lib/ruby/std_multimap.i b/Lib/ruby/std_multimap.i index 3e06ee12c..762a87653 100644 --- a/Lib/ruby/std_multimap.i +++ b/Lib/ruby/std_multimap.i @@ -90,12 +90,11 @@ %extend { VALUE __getitem__(const key_type& key) const { - MultiMap::const_iterator i = self->find(key); - if ( i != self->end() ) + std::pair r = $self->equal_range(key); + if ( r.first != r.second ) { - MultiMap::const_iterator e = $self->upper_bound(key); VALUE ary = rb_ary_new(); - for ( ; i != e; ++i ) + for (MultiMap::const_iterator i = r.first ; i != r.second; ++i ) { rb_ary_push( ary, swig::from( i->second ) ); } diff --git a/Lib/ruby/std_multiset.i b/Lib/ruby/std_multiset.i index 87a7b292a..252ae10d2 100644 --- a/Lib/ruby/std_multiset.i +++ b/Lib/ruby/std_multiset.i @@ -36,7 +36,7 @@ #define %swig_multiset_methods(Set...) %swig_set_methods(Set) - +%mixin std::multiset "Enumerable"; %rename("delete") std::multiset::__delete__; %rename("reject!") std::multiset::reject_bang; diff --git a/Lib/ruby/std_pair.i b/Lib/ruby/std_pair.i index 5bea67c7c..38a4ffb9b 100644 --- a/Lib/ruby/std_pair.i +++ b/Lib/ruby/std_pair.i @@ -31,7 +31,7 @@ int res2 = swig::asval((VALUE)second, psecond); if (!SWIG_IsOK(res2)) return res2; return res1 > res2 ? res1 : res2; - } + } } static int asval(VALUE obj, std::pair *val) { @@ -63,10 +63,16 @@ value_type *vp = %new_instance(std::pair); T *pfirst = &(vp->first); int res1 = swig::asval((VALUE)first, pfirst); - if (!SWIG_IsOK(res1)) return res1; + if (!SWIG_IsOK(res1)) { + %delete(vp); + return res1; + } U *psecond = &(vp->second); int res2 = swig::asval((VALUE)second, psecond); - if (!SWIG_IsOK(res2)) return res2; + if (!SWIG_IsOK(res2)) { + %delete(vp); + return res2; + } *val = vp; return SWIG_AddNewMask(res1 > res2 ? res1 : res2); } else { @@ -77,7 +83,7 @@ int res2 = swig::asval((VALUE)second, psecond); if (!SWIG_IsOK(res2)) return res2; return res1 > res2 ? res1 : res2; - } + } } static int asptr(VALUE obj, std::pair **val) { diff --git a/Lib/ruby/std_queue.i b/Lib/ruby/std_queue.i index a12936775..2a16d9cfd 100644 --- a/Lib/ruby/std_queue.i +++ b/Lib/ruby/std_queue.i @@ -14,7 +14,7 @@ template struct traits_from > { - static VALUE from(const std::queue & vec) { + static VALUE from(const std::queue& vec) { return traits_from_stdseq >::from(vec); } }; diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index df873679c..dee35ec03 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -1,2 +1,141 @@ #define SWIG_SHARED_PTR_NAMESPACE std %include +%include + + +%fragment("StdSharedPtrTraits","header",fragment="StdTraitsForwardDeclaration",fragment="") +{ +namespace swig { + /* + Template specialization for functions defined in rubystdcommon.swg. Special handling for shared_ptr + is required as, shared_ptr * is used rather than the usual T *, see shared_ptr.i. + */ + template + struct traits_asptr > { + static int asptr(VALUE obj, std::shared_ptr **val) { + std::shared_ptr *p = 0; + swig_type_info *descriptor = type_info >(); + swig_ruby_owntype newmem = {0, 0}; + int res = descriptor ? SWIG_ConvertPtrAndOwn(obj, (void **)&p, descriptor, 0, &newmem) : SWIG_ERROR; + if (SWIG_IsOK(res)) { + if (val) { + if (*val) { + **val = p ? *p : std::shared_ptr(); + } else { + *val = p; + if (newmem.own & SWIG_CAST_NEW_MEMORY) { + // Upcast for pointers to shared_ptr in this generic framework has not been implemented + res = SWIG_ERROR; + } + } + } + if (newmem.own & SWIG_CAST_NEW_MEMORY) + delete p; + } + return res; + } + }; + + template + struct traits_asval > { + static int asval(VALUE obj, std::shared_ptr *val) { + if (val) { + std::shared_ptr ret; + std::shared_ptr *p = &ret; + int res = traits_asptr >::asptr(obj, &p); + if (!SWIG_IsOK(res)) + return res; + *val = ret; + return SWIG_OK; + } else { + return traits_asptr >::asptr(obj, (std::shared_ptr **)(0)); + } + } + }; + + template + struct traits_asval *> { + static int asval(VALUE obj, std::shared_ptr **val) { + if (val) { + typedef typename noconst_traits >::noconst_type noconst_type; + if (*val) { + noconst_type ret; + noconst_type *p = &ret; + int res = traits_asptr::asptr(obj, &p); + if (SWIG_IsOK(res)) + **(const_cast(val)) = ret; + return res; + } else { + noconst_type *p = 0; + int res = traits_asptr::asptr(obj, &p); + if (SWIG_IsOK(res)) + *val = p; + return res; + } + } else { + return traits_asptr >::asptr(obj, (std::shared_ptr **)(0)); + } + } + }; + + template + struct traits_as, pointer_category> { + static std::shared_ptr as(VALUE obj) { + std::shared_ptr ret; + std::shared_ptr *v = &ret; + int res = traits_asptr >::asptr(obj, &v); + if (SWIG_IsOK(res)) { + return ret; + } else { + + VALUE lastErr = rb_gv_get("$!"); + if (lastErr == Qnil) + SWIG_Error(SWIG_TypeError, swig::type_name >()); + throw std::invalid_argument("bad type"); + } + } + }; + + template + struct traits_as *, pointer_category> { + static std::shared_ptr * as(VALUE obj) { + std::shared_ptr *p = 0; + int res = traits_asptr >::asptr(obj, &p); + if (SWIG_IsOK(res)) { + return p; + } else { + + VALUE lastErr = rb_gv_get("$!"); + if (lastErr == Qnil) + SWIG_Error(SWIG_TypeError, swig::type_name *>()); + throw std::invalid_argument("bad type"); + } + } + }; + + template + struct traits_from_ptr > { + static VALUE from(std::shared_ptr *val, int owner = 0) { + if (val && *val) { + return SWIG_NewPointerObj(val, type_info >(), owner); + } else { + return Qnil; + } + } + }; + + /* + The descriptors in the shared_ptr typemaps remove the const qualifier for the SWIG type system. + Remove const likewise here, otherwise SWIG_TypeQuery("std::shared_ptr") will return NULL. + */ + template + struct traits_from > { + static VALUE from(const std::shared_ptr& val) { + std::shared_ptr p = std::const_pointer_cast(val); + return swig::from(p); + } + }; +} +} + +%fragment("StdSharedPtrTraits"); diff --git a/Lib/ruby/std_stack.i b/Lib/ruby/std_stack.i index 600c81c96..7df48ef1b 100644 --- a/Lib/ruby/std_stack.i +++ b/Lib/ruby/std_stack.i @@ -14,7 +14,7 @@ template struct traits_from > { - static VALUE from(const std::stack & vec) { + static VALUE from(const std::stack& vec) { return traits_from_stdseq >::from(vec); } }; diff --git a/Lib/ruby/std_string.i b/Lib/ruby/std_string.i index cac4324f0..f9ecd8e8a 100644 --- a/Lib/ruby/std_string.i +++ b/Lib/ruby/std_string.i @@ -1,7 +1,5 @@ -%warnfilter(801) std::string; // wrong class name -%warnfilter(378) std::basic_string::operator!=; - +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) std::basic_string; AUTODOC(substr, "Return a portion of the String"); diff --git a/Lib/ruby/std_unordered_map.i b/Lib/ruby/std_unordered_map.i new file mode 100644 index 000000000..48c875214 --- /dev/null +++ b/Lib/ruby/std_unordered_map.i @@ -0,0 +1,83 @@ +// +// Maps +// +%include + +%fragment("StdUnorderedMapTraits","header",fragment="StdMapCommonTraits") +{ + namespace swig { + template + inline void + assign(const RubySeq& rubyseq, std::unordered_map *map) { + typedef typename std::unordered_map::value_type value_type; + typename RubySeq::const_iterator it = rubyseq.begin(); + for (;it != rubyseq.end(); ++it) { + map->insert(value_type(it->first, it->second)); + } + } + + template + struct traits_asptr > { + typedef std::unordered_map map_type; + static int asptr(VALUE obj, map_type **val) { + int res = SWIG_ERROR; + if (TYPE(obj) == T_HASH) { + static ID id_to_a = rb_intern("to_a"); + VALUE items = rb_funcall(obj, id_to_a, 0); + res = traits_asptr_stdseq, std::pair >::asptr(items, val); + } else { + map_type *p; + swig_type_info *descriptor = swig::type_info(); + res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; + if (SWIG_IsOK(res) && val) *val = p; + } + return res; + } + }; + + template + struct traits_from > { + typedef std::unordered_map map_type; + typedef typename map_type::const_iterator const_iterator; + typedef typename map_type::size_type size_type; + + static VALUE from(const map_type& map) { + swig_type_info *desc = swig::type_info(); + if (desc && desc->clientdata) { + return SWIG_NewPointerObj(new map_type(map), desc, SWIG_POINTER_OWN); + } else { + size_type size = map.size(); + int rubysize = (size <= (size_type) INT_MAX) ? (int) size : -1; + if (rubysize < 0) { + SWIG_RUBY_THREAD_BEGIN_BLOCK; + rb_raise(rb_eRuntimeError, "map size not valid in Ruby"); + SWIG_RUBY_THREAD_END_BLOCK; + return Qnil; + } + VALUE obj = rb_hash_new(); + for (const_iterator i= map.begin(); i!= map.end(); ++i) { + VALUE key = swig::from(i->first); + VALUE val = swig::from(i->second); + rb_hash_aset(obj, key, val); + } + return obj; + } + } + }; + } +} + +#define %swig_unordered_map_common(Map...) %swig_map_common(Map) +#define %swig_unordered_map_methods(Map...) %swig_map_methods(Map) + +%rename("delete") std::unordered_map::__delete__; +%rename("reject!") std::unordered_map::reject_bang; +%rename("map!") std::unordered_map::map_bang; +%rename("empty?") std::unordered_map::empty; +%rename("include?") std::unordered_map::__contains__ const; +%rename("has_key?") std::unordered_map::has_key const; + +%mixin std::unordered_map "Enumerable"; +%alias std::unordered_map::push "<<"; + +%include diff --git a/Lib/ruby/std_unordered_multimap.i b/Lib/ruby/std_unordered_multimap.i new file mode 100644 index 000000000..ebc53b597 --- /dev/null +++ b/Lib/ruby/std_unordered_multimap.i @@ -0,0 +1,100 @@ +/* + Multimaps +*/ +%include + +%fragment("StdUnorderedMultimapTraits","header",fragment="StdMapCommonTraits") +{ + namespace swig { + template + inline void + assign(const RubySeq& rubyseq, std::unordered_multimap *multimap) { + typedef typename std::unordered_multimap::value_type value_type; + typename RubySeq::const_iterator it = rubyseq.begin(); + for (;it != rubyseq.end(); ++it) { + multimap->insert(value_type(it->first, it->second)); + } + } + + template + struct traits_asptr > { + typedef std::unordered_multimap multimap_type; + static int asptr(VALUE obj, std::unordered_multimap **val) { + int res = SWIG_ERROR; + if ( TYPE(obj) == T_HASH ) { + static ID id_to_a = rb_intern("to_a"); + VALUE items = rb_funcall(obj, id_to_a, 0); + return traits_asptr_stdseq, std::pair >::asptr(items, val); + } else { + multimap_type *p; + res = SWIG_ConvertPtr(obj,(void**)&p,swig::type_info(),0); + if (SWIG_IsOK(res) && val) *val = p; + } + return res; + } + }; + + template + struct traits_from > { + typedef std::unordered_multimap multimap_type; + typedef typename multimap_type::const_iterator const_iterator; + typedef typename multimap_type::size_type size_type; + + static VALUE from(const multimap_type& multimap) { + swig_type_info *desc = swig::type_info(); + if (desc && desc->clientdata) { + return SWIG_NewPointerObj(new multimap_type(multimap), desc, SWIG_POINTER_OWN); + } else { + size_type size = multimap.size(); + int rubysize = (size <= (size_type) INT_MAX) ? (int) size : -1; + if (rubysize < 0) { + SWIG_RUBY_THREAD_BEGIN_BLOCK; + rb_raise(rb_eRuntimeError, + "multimap_ size not valid in Ruby"); + SWIG_RUBY_THREAD_END_BLOCK; + return Qnil; + } + VALUE obj = rb_hash_new(); + for (const_iterator i= multimap.begin(); i!= multimap.end(); ++i) { + VALUE key = swig::from(i->first); + VALUE val = swig::from(i->second); + + VALUE oldval = rb_hash_aref(obj, key); + if (oldval == Qnil) { + rb_hash_aset(obj, key, val); + } else { + // Multiple values for this key, create array if needed + // and add a new element to it. + VALUE ary; + if (TYPE(oldval) == T_ARRAY) { + ary = oldval; + } else { + ary = rb_ary_new2(2); + rb_ary_push(ary, oldval); + rb_hash_aset(obj, key, ary); + } + rb_ary_push(ary, val); + } + } + return obj; + } + } + }; + } +} + +#define %swig_unordered_multimap_methods(MultiMap...) %swig_multimap_methods(MultiMap) + +%mixin std::unordered_multimap "Enumerable"; + +%rename("delete") std::unordered_multimap::__delete__; +%rename("reject!") std::unordered_multimap::reject_bang; +%rename("map!") std::unordered_multimap::map_bang; +%rename("empty?") std::unordered_multimap::empty; +%rename("include?" ) std::unordered_multimap::__contains__ const; +%rename("has_key?" ) std::unordered_multimap::has_key const; + +%alias std::unordered_multimap::push "<<"; + +%include + diff --git a/Lib/ruby/std_unordered_multiset.i b/Lib/ruby/std_unordered_multiset.i new file mode 100644 index 000000000..dae13eef3 --- /dev/null +++ b/Lib/ruby/std_unordered_multiset.i @@ -0,0 +1,50 @@ +/* + Multisets +*/ + +%include + +%fragment("StdUnorderedMultisetTraits","header",fragment="StdUnorderedSetTraits") +%{ + namespace swig { + template + inline void + assign(const RubySeq& rubyseq, std::unordered_multiset* seq) { + // seq->insert(rubyseq.begin(), rubyseq.end()); // not used as not always implemented + typedef typename RubySeq::value_type value_type; + typename RubySeq::const_iterator it = rubyseq.begin(); + for (;it != rubyseq.end(); ++it) { + seq->insert(seq->end(),(value_type)(*it)); + } + } + + template + struct traits_asptr > { + static int asptr(VALUE obj, std::unordered_multiset **m) { + return traits_asptr_stdseq >::asptr(obj, m); + } + }; + + template + struct traits_from > { + static VALUE from(const std::unordered_multiset& vec) { + return traits_from_stdseq >::from(vec); + } + }; + } +%} + +#define %swig_unordered_multiset_methods(Set...) %swig_unordered_set_methods(Set) + +%mixin std::unordered_multiset "Enumerable"; + +%rename("delete") std::unordered_multiset::__delete__; +%rename("reject!") std::unordered_multiset::reject_bang; +%rename("map!") std::unordered_multiset::map_bang; +%rename("empty?") std::unordered_multiset::empty; +%rename("include?") std::unordered_multiset::__contains__ const; +%rename("has_key?") std::unordered_multiset::has_key const; + +%alias std::unordered_multiset::push "<<"; + +%include diff --git a/Lib/ruby/std_unordered_set.i b/Lib/ruby/std_unordered_set.i new file mode 100644 index 000000000..e8e1b0872 --- /dev/null +++ b/Lib/ruby/std_unordered_set.i @@ -0,0 +1,50 @@ +/* + Sets +*/ + +%include + +%fragment("StdUnorderedSetTraits","header",fragment="",fragment="StdSetTraits") +%{ + namespace swig { + template + inline void + assign(const RubySeq& rubyseq, std::unordered_set* seq) { + // seq->insert(rubyseq.begin(), rubyseq.end()); // not used as not always implemented + typedef typename RubySeq::value_type value_type; + typename RubySeq::const_iterator it = rubyseq.begin(); + for (;it != rubyseq.end(); ++it) { + seq->insert(seq->end(),(value_type)(*it)); + } + } + + template + struct traits_asptr > { + static int asptr(VALUE obj, std::unordered_set **s) { + return traits_asptr_stdseq >::asptr(obj, s); + } + }; + + template + struct traits_from > { + static VALUE from(const std::unordered_set& vec) { + return traits_from_stdseq >::from(vec); + } + }; + } +%} + +#define %swig_unordered_set_methods(set...) %swig_set_methods(set) + +%mixin std::unordered_set "Enumerable"; + +%rename("delete") std::unordered_set::__delete__; +%rename("reject!") std::unordered_set::reject_bang; +%rename("map!") std::unordered_set::map_bang; +%rename("empty?") std::unordered_set::empty; +%rename("include?" ) std::unordered_set::__contains__ const; +%rename("has_key?" ) std::unordered_set::has_key const; + +%alias std::unordered_set::push "<<"; + +%include diff --git a/Lib/ruby/std_wstring.i b/Lib/ruby/std_wstring.i index 5ca77c0c8..2b633438e 100644 --- a/Lib/ruby/std_wstring.i +++ b/Lib/ruby/std_wstring.i @@ -1,3 +1,52 @@ +%{ +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_RUBY_ENCODING_H +#include "ruby/encoding.h" +#endif + +/** + * The internal encoding of std::wstring is defined based on + * the size of wchar_t. If it is not appropriate for your library, + * SWIG_RUBY_WSTRING_ENCODING must be given when compiling. + */ +#ifndef SWIG_RUBY_WSTRING_ENCODING + +#if WCHAR_MAX == 0x7fff || WCHAR_MAX == 0xffff +#define SWIG_RUBY_WSTRING_ENCODING "UTF-16LE" +#elif WCHAR_MAX == 0x7fffffff || WCHAR_MAX == 0xffffffff +#define SWIG_RUBY_WSTRING_ENCODING "UTF-32LE" +#else +#error unsupported wchar_t size. SWIG_RUBY_WSTRING_ENCODING must be given. +#endif + +#endif + +/** + * If Encoding.default_internal is nil, this encoding will be used + * when converting from std::wstring to String object in Ruby. + */ +#ifndef SWIG_RUBY_INTERNAL_ENCODING +#define SWIG_RUBY_INTERNAL_ENCODING "UTF-8" +#endif + +static rb_encoding *swig_ruby_wstring_encoding; +static rb_encoding *swig_ruby_internal_encoding; + +#ifdef __cplusplus +} +#endif +%} + +%fragment("SWIG_ruby_wstring_encoding_init", "init") { + swig_ruby_wstring_encoding = rb_enc_find( SWIG_RUBY_WSTRING_ENCODING ); + swig_ruby_internal_encoding = rb_enc_find( SWIG_RUBY_INTERNAL_ENCODING ); +} + +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) std::basic_string; + %include %include diff --git a/Lib/ruby/stl.i b/Lib/ruby/stl.i index 9d2e91eee..04f86014f 100644 --- a/Lib/ruby/stl.i +++ b/Lib/ruby/stl.i @@ -1,7 +1,5 @@ /* ----------------------------------------------------------------------------- * stl.i - * - * Initial STL definition. extended as needed in each language * ----------------------------------------------------------------------------- */ %include diff --git a/Lib/scilab/boost_shared_ptr.i b/Lib/scilab/boost_shared_ptr.i index b90422a66..668bf4354 100644 --- a/Lib/scilab/boost_shared_ptr.i +++ b/Lib/scilab/boost_shared_ptr.i @@ -14,7 +14,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor wrapper customisation -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -25,7 +25,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); @@ -58,13 +58,31 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) { + int newmem = 0; + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res, "$type"); + } + if (!swig_argp) { + %dirout_nullref("$type"); + } else { + $result = *(%reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get()); + if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); + } +} + // plain pointer // Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance %typemap(in) CONST TYPE * (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -76,7 +94,7 @@ } } -%typemap(out, fragment="SWIG_null_deleter_python") CONST TYPE * { +%typemap(out, fragment="SWIG_null_deleter") CONST TYPE * { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), $owner | SWIG_POINTER_OWN)); } @@ -99,17 +117,25 @@ $1 = %const_cast((smartarg ? smartarg->get() : 0), $1_ltype); } } -%typemap(varout, fragment="SWIG_null_deleter_python") CONST TYPE * { +%typemap(varout, fragment="SWIG_null_deleter") CONST TYPE * { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE * %{ +#error "directorout typemap for plain pointer not implemented" +%} + // plain reference %typemap(in) CONST TYPE & (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { @@ -120,7 +146,7 @@ $1 = %const_cast(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get(), $1_ltype); } } -%typemap(out, fragment="SWIG_null_deleter_python") CONST TYPE & { +%typemap(out, fragment="SWIG_null_deleter") CONST TYPE & { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner); %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -144,18 +170,26 @@ $1 = *%const_cast(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get(), $1_ltype); } } -%typemap(varout, fragment="SWIG_null_deleter_python") CONST TYPE & { +%typemap(varout, fragment="SWIG_null_deleter") CONST TYPE & { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(&$1 SWIG_NO_NULL_DELETER_0); %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") CONST TYPE & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(&$1 SWIG_NO_NULL_DELETER_0); + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) CONST TYPE & %{ +#error "directorout typemap for plain reference not implemented" +%} + // plain pointer by reference // Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance %typemap(in) TYPE *CONST& (void *argp = 0, int res = 0, $*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -166,8 +200,8 @@ } $1 = &temp; } -%typemap(out, fragment="SWIG_null_deleter_python") TYPE *CONST& { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner); +%typemap(out, fragment="SWIG_null_deleter") TYPE *CONST& { + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -178,12 +212,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1, fragment="SWIG_null_deleter") TYPE *CONST& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) TYPE *CONST& %{ +#error "directorout typemap for plain pointer by reference not implemented" +%} + // shared_ptr by value %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *argp, int res = 0) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) $1 = *(%reinterpret_cast(argp, $<ype)); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $<ype); @@ -208,12 +250,28 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *swig_argp, int swig_res = 0) { + int newmem = 0; + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res, "$type"); + } + if (swig_argp) { + $result = *(%reinterpret_cast(swig_argp, $<ype)); + if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, $<ype); + } +} + // shared_ptr by reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (void *argp, int res = 0, $*1_ltype tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -235,12 +293,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{ +#error "directorout typemap for shared_ptr ref not implemented" +%} + // shared_ptr by pointer %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (void *argp, int res = 0, $*1_ltype tempshared) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -251,7 +317,7 @@ } } %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 && *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); if ($owner) delete $1; } @@ -263,12 +329,20 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{ +#error "directorout typemap for pointer to shared_ptr not implemented" +%} + // shared_ptr by pointer reference %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (void *argp, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, $*1_ltype temp = 0) { int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) tempshared = *%reinterpret_cast(argp, $*ltype); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $*ltype); @@ -276,7 +350,7 @@ $1 = &temp; } %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 && **$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -287,10 +361,18 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ + smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0; + $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +%} +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{ +#error "directorout typemap for pointer ref to shared_ptr not implemented" +%} + // Typecheck typemaps -// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting +// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, @@ -317,4 +399,3 @@ %enddef - diff --git a/Lib/scilab/scibool.swg b/Lib/scilab/scibool.swg index ea7938dc8..9aed88eca 100644 --- a/Lib/scilab/scibool.swg +++ b/Lib/scilab/scibool.swg @@ -125,7 +125,6 @@ SWIG_SciBoolean_AsIntArrayAndSize(void *pvApiCtx, int iVar, int *iRows, int *iCo } if (isBooleanType(pvApiCtx, piAddrVar)) { - int i; sciErr = getMatrixOfBoolean(pvApiCtx, piAddrVar, iRows, iCols, piValue); if (sciErr.iErr) { printError(&sciErr, 0); diff --git a/Lib/scilab/scicontainer.swg b/Lib/scilab/scicontainer.swg index 2cc44b8e5..f6078690b 100644 --- a/Lib/scilab/scicontainer.swg +++ b/Lib/scilab/scicontainer.swg @@ -42,7 +42,9 @@ %fragment("SciSequence_Cont", "header", fragment="StdTraits", - fragment="SwigSciIterator_T") + fragment="SwigSciIterator_T", + fragment=SWIG_Traits_Sequence_frag(ptr), + fragment=SWIG_Traits_SequenceItem_frag(ptr)) { namespace swig { @@ -334,8 +336,7 @@ namespace swig %fragment("StdSequenceTraits","header", fragment="StdTraits", - fragment="SciSequence_Cont", - fragment=SWIG_Traits_SequenceItem_frag(ptr)) + fragment="SciSequence_Cont") { namespace swig { template diff --git a/Lib/scilab/sciexception.swg b/Lib/scilab/sciexception.swg index a5eb4c00f..1d653b314 100644 --- a/Lib/scilab/sciexception.swg +++ b/Lib/scilab/sciexception.swg @@ -43,7 +43,7 @@ } %typemap(throws, noblock=1) char, char& { - char obj[1]; + char obj[2]; sprintf(obj, "%c", (char)$1); SWIG_Scilab_Raise_Ex(obj, "$type", $descriptor); } diff --git a/Lib/scilab/sciiterators.swg b/Lib/scilab/sciiterators.swg index 1c7ce4394..69cb04bee 100644 --- a/Lib/scilab/sciiterators.swg +++ b/Lib/scilab/sciiterators.swg @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- * sciiterators.swg * - * Users can derive form the SciSwigIterator to implemet their + * Users can derive form the SciSwigIterator to implement their * own iterators. As an example (real one since we use it for STL/STD * containers), the template SwigSciIterator_T does the * implementation for generic C++ iterators. diff --git a/Lib/scilab/scipointer.swg b/Lib/scilab/scipointer.swg index 8d0526d4d..94ca4ef37 100644 --- a/Lib/scilab/scipointer.swg +++ b/Lib/scilab/scipointer.swg @@ -6,7 +6,7 @@ } %fragment("SWIG_NewPointerObj", "header") { -#define SWIG_NewPointerObj(pointer, pointerDescriptor, flags) SwigScilabPtrFromObject(pvApiCtx, SWIG_Scilab_GetOutputPosition(), pointer, pointerDescriptor, flags) +#define SWIG_NewPointerObj(pointer, pointerDescriptor, flags) SwigScilabPtrFromObject(pvApiCtx, SWIG_Scilab_GetOutputPosition(), pointer, pointerDescriptor, flags, NULL) } /* @@ -17,7 +17,7 @@ } %fragment("SWIG_NewFunctionPtrObj", "header") { -#define SWIG_NewFunctionPtrObj(pointer, pointerDescriptor) SwigScilabPtrFromObject(pvApiCtx, SWIG_Scilab_GetOutputPosition(), pointer, pointerDescriptor, 0) +#define SWIG_NewFunctionPtrObj(pointer, pointerDescriptor) SwigScilabPtrFromObject(pvApiCtx, SWIG_Scilab_GetOutputPosition(), pointer, pointerDescriptor, 0, NULL) } // No fragment used here, the functions "SwigScilabPtrToObject" and "SwigScilabPtrFromObject" are defined in sciruntime.swg diff --git a/Lib/scilab/scirun.swg b/Lib/scilab/scirun.swg index 58c313df7..51df9a59e 100644 --- a/Lib/scilab/scirun.swg +++ b/Lib/scilab/scirun.swg @@ -49,8 +49,13 @@ static char *SWIG_Scilab_GetFuncName(void) { static void SWIG_Scilab_SetFuncName(char *funcName) { if (SwigFuncName != NULL) { free(SwigFuncName); + SwigFuncName = NULL; + } + if (funcName) { + SwigFuncName = (char *)malloc(strlen(funcName) + 1); + if (SwigFuncName) + strcpy(SwigFuncName, funcName); } - SwigFuncName = strdup(funcName); } /* Api context management functions */ @@ -100,8 +105,83 @@ SWIG_Scilab_SetOutput(void *pvApiCtx, SwigSciObject output) { return SWIG_OK; } +/* Error functions */ + +#define SCILAB_API_ARGUMENT_ERROR 999 + +SWIGINTERN const char* +SWIG_Scilab_ErrorType(int code) { + switch(code) { + case SWIG_MemoryError: + return "MemoryError"; + case SWIG_IOError: + return "IOError"; + case SWIG_RuntimeError: + return "RuntimeError"; + case SWIG_IndexError: + return "IndexError"; + case SWIG_TypeError: + return "TypeError"; + case SWIG_DivisionByZero: + return "ZeroDivisionError"; + case SWIG_OverflowError: + return "OverflowError"; + case SWIG_SyntaxError: + return "SyntaxError"; + case SWIG_ValueError: + return "ValueError"; + case SWIG_SystemError: + return "SystemError"; + case SWIG_AttributeError: + return "AttributeError"; + default: + return "RuntimeError"; + } +} +#define SWIG_ErrorType(code) SWIG_Scilab_ErrorType(code) + +#ifndef SWIG_SCILAB_ERROR +#define SWIG_SCILAB_ERROR 20000 +#endif + +SWIGINTERN void +SWIG_Scilab_Error(int code, const char *msg) { + Scierror(SWIG_SCILAB_ERROR - code, _("SWIG/Scilab: %s: %s\n"), SWIG_Scilab_ErrorType(code), msg); +} + +#define SWIG_Error(code, msg) SWIG_Scilab_Error(code, msg) + +#define SWIG_fail return SWIG_ERROR; + +SWIGRUNTIME void +SWIG_Scilab_Raise_Ex(const char *obj, const char *type, swig_type_info *descriptor) { + if (type) { + if (obj) + Scierror(SWIG_SCILAB_ERROR, "SWIG/Scilab: Exception (%s) occurred: %s\n", type, obj); + else + Scierror(SWIG_SCILAB_ERROR, "SWIG/Scilab: Exception (%s) occurred.\n", type); + } +} + +SWIGRUNTIME void +SWIG_Scilab_Raise(const int obj, const char *type, swig_type_info *descriptor) { + Scierror(SWIG_SCILAB_ERROR, "SWIG/Scilab: Exception (%s) occurred.\n", type); +} + +/* Module initialization */ + +static int swig_module_initialized = 0; + +SWIGRUNTIME int +SWIG_Module_Initialized() { + return swig_module_initialized; +} + /* Pointer conversion functions */ +SWIGRUNTIME swig_type_info * +SWIG_Scilab_TypeQuery(const char *name); + SWIGINTERN int SwigScilabCheckPtr(void *pvApiCtx, int iVar, swig_type_info *descriptor, char *fname) { SciErr sciErr; @@ -142,10 +222,10 @@ SwigScilabCheckPtr(void *pvApiCtx, int iVar, swig_type_info *descriptor, char *f if (descriptor) { swig_cast_info *cast = SWIG_TypeCheck(SWIG_TypeName((swig_type_info*)pvTypeinfo), descriptor); return (cast != NULL); - } + } else { return SWIG_ERROR; - } + } } else { return (iType == sci_pointer); @@ -176,8 +256,7 @@ SwigScilabPtrToObject(void *pvApiCtx, int iVar, void **pvObj, swig_type_info *de void *pvTypeinfo = NULL; sciErr = getListItemNumber(pvApiCtx, piAddrVar, &iItemCount); - if (sciErr.iErr) - { + if (sciErr.iErr) { printError(&sciErr, 0); return SWIG_ERROR; } @@ -224,7 +303,10 @@ SwigScilabPtrToObject(void *pvApiCtx, int iVar, void **pvObj, swig_type_info *de if (pvObj) { *pvObj = pvPtr; - return SWIG_OK; + if (pvPtr) + return SWIG_OK; + else + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } else { return SWIG_ERROR; @@ -232,12 +314,11 @@ SwigScilabPtrToObject(void *pvApiCtx, int iVar, void **pvObj, swig_type_info *de } SWIGRUNTIMEINLINE int -SwigScilabPtrFromObject(void *pvApiCtx, int iVarOut, void *pvObj, swig_type_info *descriptor, int flags) { +SwigScilabPtrFromObject(void *pvApiCtx, int iVarOut, void *pvObj, swig_type_info *descriptor, int flags, const char *pstTypeName) { SciErr sciErr; if (descriptor) { int *piMListAddr = NULL; - const char *pstString; sciErr = createMList(pvApiCtx, SWIG_NbInputArgument(pvApiCtx) + iVarOut, 3, &piMListAddr); if (sciErr.iErr) { @@ -245,8 +326,11 @@ SwigScilabPtrFromObject(void *pvApiCtx, int iVarOut, void *pvObj, swig_type_info return SWIG_ERROR; } - pstString = SWIG_TypeName(descriptor); - sciErr = createMatrixOfStringInList(pvApiCtx, SWIG_NbInputArgument(pvApiCtx) + iVarOut, piMListAddr, 1, 1, 1, &pstString); + if (pstTypeName == NULL) { + pstTypeName = SWIG_TypeName(descriptor); + } + + sciErr = createMatrixOfStringInList(pvApiCtx, SWIG_NbInputArgument(pvApiCtx) + iVarOut, piMListAddr, 1, 1, 1, &pstTypeName); if (sciErr.iErr) { printError(&sciErr, 0); return SWIG_ERROR; @@ -258,7 +342,6 @@ SwigScilabPtrFromObject(void *pvApiCtx, int iVarOut, void *pvObj, swig_type_info return SWIG_ERROR; } - sciErr = createPointerInList(pvApiCtx, SWIG_NbInputArgument(pvApiCtx) + iVarOut, piMListAddr, 3, pvObj); if (sciErr.iErr) { printError(&sciErr, 0); @@ -342,69 +425,7 @@ SWIG_Scilab_NewMemberObj(void *pvApiCtx, int iVarOut, void *ptr, int sz, swig_ty } -/* Error functions */ -#define SCILAB_API_ARGUMENT_ERROR 999 - -SWIGINTERN const char* -SWIG_Scilab_ErrorType(int code) { - switch(code) { - case SWIG_MemoryError: - return "MemoryError"; - case SWIG_IOError: - return "IOError"; - case SWIG_RuntimeError: - return "RuntimeError"; - case SWIG_IndexError: - return "IndexError"; - case SWIG_TypeError: - return "TypeError"; - case SWIG_DivisionByZero: - return "ZeroDivisionError"; - case SWIG_OverflowError: - return "OverflowError"; - case SWIG_SyntaxError: - return "SyntaxError"; - case SWIG_ValueError: - return "ValueError"; - case SWIG_SystemError: - return "SystemError"; - case SWIG_AttributeError: - return "AttributeError"; - default: - return "RuntimeError"; - } -} -#define SWIG_ErrorType(code) SWIG_Scilab_ErrorType(code) - -#ifndef SWIG_SCILAB_ERROR -#define SWIG_SCILAB_ERROR 20000 -#endif - -SWIGINTERN void -SWIG_Scilab_Error(int code, const char *msg) -{ - Scierror(SWIG_SCILAB_ERROR - code, _("SWIG/Scilab: %s: %s\n"), SWIG_Scilab_ErrorType(code), msg); -} - -#define SWIG_Error(code, msg) SWIG_Scilab_Error(code, msg) - -#define SWIG_fail return SWIG_ERROR; - -SWIGRUNTIME void -SWIG_Scilab_Raise_Ex(const char *obj, const char *type, swig_type_info *descriptor) { - if (type) { - if (obj) - Scierror(SWIG_SCILAB_ERROR, "SWIG/Scilab: Exception (%s) occured: %s\n", type, obj); - else - Scierror(SWIG_SCILAB_ERROR, "SWIG/Scilab: Exception (%s) occured.\n", type); - } -} - -SWIGRUNTIME void -SWIG_Scilab_Raise(const int obj, const char *type, swig_type_info *descriptor) { - Scierror(SWIG_SCILAB_ERROR, "SWIG/Scilab: Exception (%s) occured.\n", type); -} /* * Pointer utility functions @@ -433,27 +454,81 @@ int SWIG_this(SWIG_GatewayParameters) { extern "C" #endif int SWIG_ptr(SWIG_GatewayParameters) { - double dValue = 0; - int *piAddr; - SciErr sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr); - if(sciErr.iErr) { - printError(&sciErr, 0); - return SWIG_ERROR; - } - if (getScalarDouble(pvApiCtx, piAddr, &dValue) == 0) { - if (dValue != (uintptr_t)dValue) { - Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Incorrect value for input argument #%d: The double value cannot be converted to a pointer.\n"), fname, 1); - return SWIG_ValueError; + if (SWIG_NbInputArgument(pvApiCtx) > 0) { + SciErr sciErr; + int *piAddrVar1 = NULL; + int iTypeVar1 = 0; + char *pstInputPtrTypeName = NULL; + char *pstOutputMListTypeName = NULL; + if (SWIG_NbInputArgument(pvApiCtx) > 2) { + int *piAddrVar2 = NULL; + int *piAddrVar3 = NULL; + sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddrVar2); + if (sciErr.iErr) { + printError(&sciErr, 0); + return SWIG_ERROR; + } + if (getAllocatedSingleString(pvApiCtx, piAddrVar2, &pstInputPtrTypeName)) { + return SWIG_ERROR; + } + sciErr = getVarAddressFromPosition(pvApiCtx, 3, &piAddrVar3); + if (sciErr.iErr) { + printError(&sciErr, 0); + return SWIG_ERROR; + } + if (getAllocatedSingleString(pvApiCtx, piAddrVar3, &pstOutputMListTypeName)) { + return SWIG_ERROR; + } } - if ((dValue < 0) || (dValue > ULONG_MAX)) { - Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Overflow error for input argument #%d: The double value cannot be converted to a pointer.\n"), fname, 1); - return SWIG_OverflowError; + + sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddrVar1); + if (sciErr.iErr) { + printError(&sciErr, 0); + return SWIG_ERROR; + } + sciErr = getVarType(pvApiCtx, piAddrVar1, &iTypeVar1); + if (sciErr.iErr) { + printError(&sciErr, 0); + return SWIG_ERROR; + } + + if ((iTypeVar1 == sci_pointer) || (iTypeVar1 == sci_mlist)) { + void *ptrValue = NULL; + if (SwigScilabPtrToObject(pvApiCtx, 1, &ptrValue, SWIG_Scilab_TypeQuery(pstInputPtrTypeName), 0, (char *) "SWIG_ptr") == SWIG_OK) { + SWIG_Scilab_SetOutputPosition(1); + return SWIG_Scilab_SetOutput(pvApiCtx, + SwigScilabPtrFromObject(pvApiCtx, 1, ptrValue, SWIG_Scilab_TypeQuery(pstInputPtrTypeName), 0, pstOutputMListTypeName)); + } + else { + return SWIG_ERROR; + } + } + else if (iTypeVar1 == sci_matrix) { + double dValue = 0; + if (getScalarDouble(pvApiCtx, piAddrVar1, &dValue) == 0) { + if (dValue != (uintptr_t)dValue) { + Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Incorrect value for input argument #%d: The double value cannot be converted to a pointer.\n"), fname, 1); + return SWIG_ValueError; + } + if ((dValue < 0) || (dValue > ULONG_MAX)) { + Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Overflow error for input argument #%d: The double value cannot be converted to a pointer.\n"), fname, 1); + return SWIG_OverflowError; + } + SWIG_Scilab_SetOutputPosition(1); + return SWIG_Scilab_SetOutput(pvApiCtx, + SwigScilabPtrFromObject(pvApiCtx, 1, (void *) (uintptr_t)dValue, SWIG_Scilab_TypeQuery(pstInputPtrTypeName), 0, pstOutputMListTypeName)); + } + else { + return SWIG_TypeError; + } + } + else { + Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Wrong type for input argument #%d: A mlist, pointer or a double expected.\n"), (char *) "SWIG_ptr", 1); + return SWIG_TypeError; } - SWIG_Scilab_SetOutputPosition(1); - return SWIG_Scilab_SetOutput(pvApiCtx, - SwigScilabPtrFromObject(pvApiCtx, 1, (void *) (uintptr_t)dValue, NULL, 0)); } else { - return SWIG_ERROR; + Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: A mlist, pointer, or a double expected.\n"), "SWIG_ptr", 1); + return SWIG_TypeError; } } diff --git a/Lib/scilab/sciruntime.swg b/Lib/scilab/sciruntime.swg index 9832ed411..3de138e11 100644 --- a/Lib/scilab/sciruntime.swg +++ b/Lib/scilab/sciruntime.swg @@ -1,33 +1,47 @@ %insert(runtime) "swigrun.swg"; %insert(runtime) "swigerrors.swg"; -#define %scilabcode %insert("scilab") - %insert(runtime) "scirun.swg"; -%init %{ +%insert(init) %{ +/* Module management functions */ + #define SWIG_GetModule(clientdata) SWIG_Scilab_GetModule() #define SWIG_SetModule(clientdata, pointer) SWIG_Scilab_SetModule(pointer) SWIGRUNTIME swig_module_info* -SWIG_Scilab_GetModule(void) -{ +SWIG_Scilab_GetModule(void) { return NULL; } SWIGRUNTIME void -SWIG_Scilab_SetModule(swig_module_info *swig_module) -{ +SWIG_Scilab_SetModule(swig_module_info *swig_module) { } %} %insert(init) "swiginit.swg" -%init %{ +%insert(init) %{ +SWIGRUNTIME swig_type_info * +SWIG_Scilab_TypeQuery(const char *name) { + if (SWIG_Module_Initialized()) { + if (name) { + return SWIG_TypeQuery(name); + } + } + else { + SWIG_Error(SWIG_RuntimeError, "the module is not initialized"); + } + return NULL; +} +%} + +%insert(init) %{ #ifdef __cplusplus extern "C" #endif int _Init(SWIG_GatewayParameters) { SWIG_InitializeModule(NULL); SWIG_CreateScilabVariables(pvApiCtx); + swig_module_initialized = 1; %} diff --git a/Lib/scilab/scisequencebool.swg b/Lib/scilab/scisequencebool.swg index 0430c3e39..b7d078448 100644 --- a/Lib/scilab/scisequencebool.swg +++ b/Lib/scilab/scisequencebool.swg @@ -84,7 +84,7 @@ SWIG_FromSet_Sequence_dec(bool)(int size, int *pSequence) { SWIGINTERN bool SWIG_AsVal_SequenceItem_dec(bool)(SwigSciObject obj, int *pSequence, int iItemIndex) { - return pSequence[iItemIndex]; + return (bool) pSequence[iItemIndex]; } } diff --git a/Lib/scilab/scisequencestring.swg b/Lib/scilab/scisequencestring.swg index 36f0927a8..d3c05e4f8 100644 --- a/Lib/scilab/scisequencestring.swg +++ b/Lib/scilab/scisequencestring.swg @@ -1,5 +1,5 @@ /* - *char + * * Scilab matrix of string <-> C++ std::string container * */ @@ -88,7 +88,7 @@ SWIG_AsVal_SequenceItem_dec(std::string)(SwigSciObject obj, char **pSequence, in SWIGINTERN int SWIG_From_SequenceItem_dec(std::string)(char **pSequence, int iItemIndex, std::string itemValue) { - char *pChar = new char(itemValue.size() + 1); + char *pChar = new char((int) itemValue.size() + 1); strcpy(pChar, itemValue.c_str()); pSequence[iItemIndex] = pChar; return SWIG_OK; diff --git a/Lib/scilab/scistdcommon.swg b/Lib/scilab/scistdcommon.swg index 63f3ca164..b08fc0307 100644 --- a/Lib/scilab/scistdcommon.swg +++ b/Lib/scilab/scistdcommon.swg @@ -41,7 +41,7 @@ namespace swig { template struct traits_asptr { static int asptr(const SwigSciObject& obj, Type **val) { - Type *p; + Type *p = 0; swig_type_info *descriptor = type_info(); int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; if (SWIG_IsOK(res)) { @@ -104,23 +104,21 @@ namespace swig { template struct traits_as { - static Type as(const SwigSciObject& obj, bool throw_error) { + static Type as(const SwigSciObject& obj) { Type v; int res = asval(obj, &v); if (SWIG_IsOK(res)) { return v; } else { - %type_error(swig::type_name()); - if (throw_error) - throw std::invalid_argument("bad type"); - return res; + %type_error(swig::type_name()); + throw std::invalid_argument("bad type"); } } }; template struct traits_as { - static Type as(const SwigSciObject& obj, bool throw_error) { + static Type as(const SwigSciObject& obj) { Type *v = 0; int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res) && v) { @@ -132,36 +130,29 @@ namespace swig { return *v; } } else { - // Uninitialized return value, no Type() constructor required. - static Type *v_def = (Type*) malloc(sizeof(Type)); - %type_error(swig::type_name()); - if (throw_error) - throw std::invalid_argument("bad type"); - memset(v_def,0,sizeof(Type)); - return *v_def; + %type_error(swig::type_name()); + throw std::invalid_argument("bad type"); } } }; template struct traits_as { - static Type* as(const SwigSciObject& obj, bool throw_error) { + static Type* as(const SwigSciObject& obj) { Type *v = 0; int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res)) { return v; } else { - %type_error(swig::type_name()); - if (throw_error) - throw std::invalid_argument("bad type"); - return SWIG_OK; + %type_error(swig::type_name()); + throw std::invalid_argument("bad type"); } } }; template - inline Type as(const SwigSciObject& obj, bool te = false) { - return traits_as::category>::as(obj, te); + inline Type as(const SwigSciObject& obj) { + return traits_as::category>::as(obj); } template diff --git a/Lib/scilab/scitypemaps.swg b/Lib/scilab/scitypemaps.swg index 175a41b51..99fdce7be 100644 --- a/Lib/scilab/scitypemaps.swg +++ b/Lib/scilab/scitypemaps.swg @@ -7,7 +7,7 @@ #define SWIG_Object int #define %append_output(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR -#define %set_constant(name, obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR // Name is managed by the the function name +#define %set_constant(name, obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR // Name is managed by the function name #define %raise(obj, type, desc) SWIG_Scilab_Raise(obj, type, desc) #define %set_output(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR #define %set_varoutput(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR @@ -97,7 +97,7 @@ if (SWIG_AsVal_dec(Enum)($input, &val) != SWIG_OK) { return SWIG_ERROR; } - $1 = %reinterpret_cast(val, $ltype); + $1 = %static_cast(val, $1_ltype); } %typemap(out, fragment=SWIG_From_frag(Enum)) enum SWIGTYPE { @@ -122,28 +122,37 @@ } %enddef -/* Scilab equivalent for C integers can be sci_ints or sci_matrix */ -%define %scilab_typecheck_integer(PRECEDENCE, INTTYPE, TYPE) -%typecheck(PRECEDENCE) TYPE { +%fragment("SWIG_Check_SciDoubleOrInt", "header") { +SWIGINTERN int +SWIG_Check_SciDoubleOrInt(void *pvApiCtx, SwigSciObject iVar, int iIntegerType) { int *piAddrVar = NULL; - SciErr sciErr = getVarAddressFromPosition(pvApiCtx, $input, &piAddrVar); + int ret = 0; + SciErr sciErr = getVarAddressFromPosition(pvApiCtx, iVar, &piAddrVar); if (sciErr.iErr) { printError(&sciErr, 0); - return SWIG_ERROR; + return 0; } - $1 = isIntegerType(pvApiCtx, piAddrVar); - if ($1 == 1) { + ret = isIntegerType(pvApiCtx, piAddrVar); + if (ret == 1) { int iPrec = 0; sciErr = getMatrixOfIntegerPrecision(pvApiCtx, piAddrVar, &iPrec); if (sciErr.iErr) { printError(&sciErr, 0); - return SWIG_ERROR; + return 0; } - $1 = (iPrec == INTTYPE) ? 1 : 0; + ret = (iPrec == iIntegerType) ? 1 : 0; } else { - $1 = isDoubleType(pvApiCtx, piAddrVar); + ret = isDoubleType(pvApiCtx, piAddrVar); } + return ret; +} +} + +/* Scilab equivalent for C integers can be sci_intXX or sci_matrix */ +%define %scilab_typecheck_integer(PRECEDENCE, INTTYPE, TYPE) +%typecheck(PRECEDENCE, fragment="SWIG_Check_SciDoubleOrInt") TYPE { + $1 = SWIG_Check_SciDoubleOrInt(pvApiCtx, $input, INTTYPE); } %enddef diff --git a/Lib/scilab/std_basic_string.i b/Lib/scilab/std_basic_string.i index 43b660db6..b57353816 100644 --- a/Lib/scilab/std_basic_string.i +++ b/Lib/scilab/std_basic_string.i @@ -21,8 +21,7 @@ SWIG_AsPtr_dec(std::basic_string)(int _iVar, std::basic_string **_ps delete[] buf; } return SWIG_NEWOBJ; - } - else { + } else { if (_pstValue) { *_pstValue = NULL; } diff --git a/Lib/scilab/std_map.i b/Lib/scilab/std_map.i index 250d2d84c..07eb63fda 100644 --- a/Lib/scilab/std_map.i +++ b/Lib/scilab/std_map.i @@ -19,18 +19,28 @@ namespace std { - template class map { + template > class map { // add typemaps here public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -40,14 +50,14 @@ namespace std { (*self)[key] = x; } void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } } diff --git a/Lib/scilab/std_pair.i b/Lib/scilab/std_pair.i index 1448d6524..39ef008d3 100644 --- a/Lib/scilab/std_pair.i +++ b/Lib/scilab/std_pair.i @@ -18,12 +18,14 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/scilab/std_shared_ptr.i b/Lib/scilab/std_shared_ptr.i new file mode 100644 index 000000000..df873679c --- /dev/null +++ b/Lib/scilab/std_shared_ptr.i @@ -0,0 +1,2 @@ +#define SWIG_SHARED_PTR_NAMESPACE std +%include diff --git a/Lib/scilab/stl.i b/Lib/scilab/stl.i index b29f7d84d..04f86014f 100644 --- a/Lib/scilab/stl.i +++ b/Lib/scilab/stl.i @@ -1,6 +1,10 @@ -/* initial STL definition. extended as needed in each language */ +/* ----------------------------------------------------------------------------- + * stl.i + * ----------------------------------------------------------------------------- */ + %include %include %include %include %include + diff --git a/Lib/shared_ptr.i b/Lib/shared_ptr.i index 450493db4..eada0b9e7 100644 --- a/Lib/shared_ptr.i +++ b/Lib/shared_ptr.i @@ -4,6 +4,13 @@ // to use a pointer to the smart pointer of the type, rather than the usual pointer to the underlying type. // So for some type T, shared_ptr * is used rather than T *. +// Another key part of the implementation is the smartptr feature: +// %feature("smartptr") T { shared_ptr } +// This feature marks the class T as having a smartptr to it (the shared_ptr type). This is then used to +// support smart pointers and inheritance. Say class D derives from base B, then shared_ptr is marked +// with a fake inheritance from shared_ptr in the type system if the "smartptr" feature is used on both +// B and D. This is to emulate the conversion of shared_ptr to shared_ptr in the target language. + // shared_ptr namespaces could be boost or std or std::tr1 // For example for std::tr1, use: // #define SWIG_SHARED_PTR_NAMESPACE std @@ -42,12 +49,10 @@ struct SWIG_null_deleter { } -// Workaround empty first macro argument bug -#define SWIGEMPTYHACK // Main user macro for defining shared_ptr typemaps for both const and non-const pointer types %define %shared_ptr(TYPE...) %feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > } -SWIG_SHARED_PTR_TYPEMAPS(SWIGEMPTYHACK, TYPE) +SWIG_SHARED_PTR_TYPEMAPS(, TYPE) SWIG_SHARED_PTR_TYPEMAPS(const, TYPE) %enddef diff --git a/Lib/std/_std_deque.i b/Lib/std/_std_deque.i index e860e947f..af9db27f4 100644 --- a/Lib/std/_std_deque.i +++ b/Lib/std/_std_deque.i @@ -24,7 +24,7 @@ }; */ -%define %std_deque_methods_noempty(T) +%define %std_deque_methods_noempty(T...) typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; @@ -116,7 +116,7 @@ %enddef #ifdef SWIGPHP -%define %std_deque_methods(T) +%define %std_deque_methods(T...) %extend { bool is_empty() const { return self->empty(); @@ -125,7 +125,7 @@ %std_deque_methods_noempty(T) %enddef #else -%define %std_deque_methods(T) +%define %std_deque_methods(T...) bool empty() const; %std_deque_methods_noempty(T) %enddef diff --git a/Lib/std/std_alloc.i b/Lib/std/std_alloc.i index 44dc8dc3e..e460dc3ea 100644 --- a/Lib/std/std_alloc.i +++ b/Lib/std/std_alloc.i @@ -31,9 +31,9 @@ namespace std allocator() throw(); - allocator(const allocator&) throw(); + allocator(const allocator& other) throw(); template - allocator(const allocator<_Tp1>&) throw(); + allocator(const allocator<_Tp1>& other) throw(); ~allocator() throw(); diff --git a/Lib/std/std_array.i b/Lib/std/std_array.i index aadc3b80c..3f70ef57c 100644 --- a/Lib/std/std_array.i +++ b/Lib/std/std_array.i @@ -53,8 +53,8 @@ namespace std { typedef _Tp value_type; typedef value_type* pointer; typedef const value_type* const_pointer; - typedef _Tp& reference; - typedef const _Tp& const_reference; + typedef value_type& reference; + typedef const value_type& const_reference; %traits_swigtype(_Tp); %traits_enum(_Tp); diff --git a/Lib/std/std_carray.swg b/Lib/std/std_carray.swg index ebb20ce6a..de2a07627 100644 --- a/Lib/std/std_carray.swg +++ b/Lib/std/std_carray.swg @@ -28,8 +28,8 @@ namespace std { carray() { } - carray(const carray& c) { - std::copy(c.v, c.v + size(), v); + carray(const carray& other) { + std::copy(other.v, other.v + size(), v); } template diff --git a/Lib/std/std_common.i b/Lib/std/std_common.i index 05bc4325a..708f3ceed 100644 --- a/Lib/std/std_common.i +++ b/Lib/std/std_common.i @@ -5,7 +5,7 @@ // //#define SWIG_STD_MODERN_STL // -// Use this to deactive the previous definition, when using gcc-2.95 +// Use this to deactivate the previous definition, when using gcc-2.95 // or similar old compilers. // //#define SWIG_STD_NOMODERN_STL diff --git a/Lib/std/std_container.i b/Lib/std/std_container.i index 5fa085afa..570dfde48 100644 --- a/Lib/std/std_container.i +++ b/Lib/std/std_container.i @@ -11,20 +11,30 @@ %define %std_container_methods_non_resizable(container...) container(); - container(const container&); + container(const container& other); bool empty() const; size_type size() const; void swap(container& v); +%enddef + +%define %std_container_methods_forward_iterators(container...) + #ifdef SWIG_EXPORT_ITERATOR_METHODS class iterator; - class reverse_iterator; class const_iterator; - class const_reverse_iterator; - iterator begin(); iterator end(); + #endif + +%enddef + +%define %std_container_methods_reverse_iterators(container...) + + #ifdef SWIG_EXPORT_ITERATOR_METHODS + class reverse_iterator; + class const_reverse_iterator; reverse_iterator rbegin(); reverse_iterator rend(); #endif @@ -34,7 +44,20 @@ // Common container methods %define %std_container_methods(container...) + %std_container_methods_non_resizable(%arg(container)) + %std_container_methods_forward_iterators(%arg(container)) + %std_container_methods_reverse_iterators(%arg(container)) + + void clear(); + allocator_type get_allocator() const; + +%enddef + +%define %std_container_methods_without_reverse_iterators(container...) + + %std_container_methods_non_resizable(%arg(container)) + %std_container_methods_forward_iterators(%arg(container)) void clear(); allocator_type get_allocator() const; @@ -65,6 +88,8 @@ %define %std_sequence_methods_non_resizable(sequence) %std_container_methods_non_resizable(%arg(sequence)) + %std_container_methods_forward_iterators(%arg(container)) + %std_container_methods_reverse_iterators(%arg(container)) const value_type& front() const; const value_type& back() const; @@ -97,6 +122,8 @@ %define %std_sequence_methods_non_resizable_val(sequence...) %std_container_methods_non_resizable(%arg(sequence)) + %std_container_methods_forward_iterators(%arg(container)) + %std_container_methods_reverse_iterators(%arg(container)) value_type front() const; value_type back() const; diff --git a/Lib/std/std_deque.i b/Lib/std/std_deque.i index 29560caed..aa5536bf6 100644 --- a/Lib/std/std_deque.i +++ b/Lib/std/std_deque.i @@ -120,7 +120,7 @@ namespace std { %swig_deque_methods_val(std::deque< _Tp*, _Alloc >); #endif - %std_deque_methods_val(std::deque< _Tp*, _Alloc >); + %std_deque_methods_val(deque); }; } diff --git a/Lib/std/std_except.i b/Lib/std/std_except.i index 75b8d0fd6..728b9c8b5 100644 --- a/Lib/std/std_except.i +++ b/Lib/std/std_except.i @@ -3,6 +3,7 @@ #endif %{ +#include #include %} @@ -15,6 +16,10 @@ namespace std { virtual const char* what() const throw(); }; + struct bad_cast : exception + { + }; + struct bad_exception : exception { }; diff --git a/Lib/std/std_ios.i b/Lib/std/std_ios.i index db83c7abf..7c62ed690 100644 --- a/Lib/std/std_ios.i +++ b/Lib/std/std_ios.i @@ -153,10 +153,10 @@ namespace std { //50. Copy constructor and assignment operator of ios_base private: - ios_base(const ios_base&); + ios_base(const ios_base& other); ios_base& - operator=(const ios_base&); + operator=(const ios_base& other); }; template > @@ -242,10 +242,10 @@ namespace std { // 27.4.5.1 basic_ios constructors basic_ios(); private: - basic_ios(const basic_ios&); + basic_ios(const basic_ios& other); basic_ios& - operator=(const basic_ios&); + operator=(const basic_ios& other); }; } diff --git a/Lib/std/std_iostream.i b/Lib/std/std_iostream.i index 7a33afe39..38a22963f 100644 --- a/Lib/std/std_iostream.i +++ b/Lib/std/std_iostream.i @@ -306,15 +306,15 @@ namespace std template > std::basic_ostream<_CharT, _Traits>& - endl(std::basic_ostream<_CharT, _Traits>&); + endl(std::basic_ostream<_CharT, _Traits>& value); template > std::basic_ostream<_CharT, _Traits>& - ends(std::basic_ostream<_CharT, _Traits>&); + ends(std::basic_ostream<_CharT, _Traits>& value); template > std::basic_ostream<_CharT, _Traits>& - flush(std::basic_ostream<_CharT, _Traits>&); + flush(std::basic_ostream<_CharT, _Traits>& value); } namespace std { diff --git a/Lib/std/std_list.i b/Lib/std/std_list.i index 1aaec0aa9..2cc2d97cf 100644 --- a/Lib/std/std_list.i +++ b/Lib/std/std_list.i @@ -6,7 +6,7 @@ // List -%define %std_list_methods(list) +%define %std_list_methods(list...) %std_sequence_methods(list) void pop_front(); @@ -17,7 +17,7 @@ %enddef -%define %std_list_methods_val(list) +%define %std_list_methods_val(list...) %std_sequence_methods_val(list) void pop_front(); @@ -106,8 +106,8 @@ namespace std { typedef _Tp* value_type; typedef value_type* pointer; typedef const value_type* const_pointer; - typedef value_type reference; - typedef value_type const_reference; + typedef value_type& reference; + typedef const value_type& const_reference; typedef _Alloc allocator_type; %traits_swigtype(_Tp); diff --git a/Lib/std/std_map.i b/Lib/std/std_map.i index 8043f924c..62f5cb37c 100644 --- a/Lib/std/std_map.i +++ b/Lib/std/std_map.i @@ -74,7 +74,6 @@ namespace std { typedef _Key key_type; typedef _Tp mapped_type; typedef std::pair< const _Key, _Tp > value_type; - typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; @@ -113,7 +112,7 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_MAP, std::map< _Key, _Tp, _Compare, _Alloc >); - map( const _Compare& ); + map(const _Compare& other); #ifdef %swig_map_methods // Add swig/language extra methods diff --git a/Lib/std/std_multimap.i b/Lib/std/std_multimap.i index 7aa949907..03e765341 100644 --- a/Lib/std/std_multimap.i +++ b/Lib/std/std_multimap.i @@ -50,7 +50,6 @@ namespace std { typedef _Key key_type; typedef _Tp mapped_type; typedef std::pair< const _Key, _Tp > value_type; - typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; @@ -89,7 +88,7 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_MULTIMAP, std::multimap< _Key, _Tp, _Compare, _Alloc >); - multimap( const _Compare& ); + multimap(const _Compare& other); #ifdef %swig_multimap_methods // Add swig/language extra methods diff --git a/Lib/std/std_multiset.i b/Lib/std/std_multiset.i index 1aa7ccce8..a1d0db813 100644 --- a/Lib/std/std_multiset.i +++ b/Lib/std/std_multiset.i @@ -71,7 +71,7 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_MULTISET, std::multiset< _Key, _Compare, _Alloc >); - multiset( const _Compare& ); + multiset(const _Compare& other); #ifdef %swig_multiset_methods // Add swig/language extra methods diff --git a/Lib/std/std_pair.i b/Lib/std/std_pair.i index 001cd6738..800155f21 100644 --- a/Lib/std/std_pair.i +++ b/Lib/std/std_pair.i @@ -35,9 +35,9 @@ namespace std { pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair< U1, U2 > &p); + template pair(const pair< U1, U2 > &other); T first; U second; @@ -76,8 +76,8 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_PAIR, std::pair< T, U* >); pair(); - pair(T __a, U* __b); - pair(const pair& __p); + pair(T first, U* second); + pair(const pair& other); T first; U* second; @@ -112,8 +112,8 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_PAIR, std::pair< T*, U >); pair(); - pair(T* __a, U __b); - pair(const pair& __p); + pair(T* first, U second); + pair(const pair& other); T* first; U second; @@ -148,8 +148,8 @@ namespace std { %typemap_traits(SWIG_TYPECHECK_PAIR, std::pair< T*, U* >); pair(); - pair(T* __a, U* __b); - pair(const pair& __p); + pair(T* first, U* second); + pair(const pair& other); T* first; U* second; diff --git a/Lib/std/std_queue.i b/Lib/std/std_queue.i index 7452a4b60..51bb04473 100644 --- a/Lib/std/std_queue.i +++ b/Lib/std/std_queue.i @@ -13,14 +13,14 @@ %define %std_queue_methods(queue...) queue(); - queue( const _Sequence& ); + queue(const _Sequence& other); bool empty() const; size_type size() const; const value_type& front() const; const value_type& back() const; void pop(); - void push( const value_type& ); + void push(const value_type& value); %enddef %define %std_queue_methods_val(queue...) @@ -122,7 +122,7 @@ namespace std { %swig_queue_methods_val(std::queue< _Tp*, _Sequence >); #endif - %std_queue_methods_val(std::queue< _Tp*, _Sequence >); + %std_queue_methods_val(queue); }; } diff --git a/Lib/std/std_set.i b/Lib/std/std_set.i index 107a23c71..0e05aca40 100644 --- a/Lib/std/std_set.i +++ b/Lib/std/std_set.i @@ -8,7 +8,7 @@ // Set %define %std_set_methods_common(set...) set(); - set( const set& ); + set(const set& other); bool empty() const; size_type size() const; @@ -110,7 +110,7 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_SET, std::set< _Key, _Compare, _Alloc >); - set( const _Compare& ); + set(const _Compare& other); #ifdef %swig_set_methods // Add swig/language extra methods diff --git a/Lib/std/std_stack.i b/Lib/std/std_stack.i index 48dae0585..ff714d099 100644 --- a/Lib/std/std_stack.i +++ b/Lib/std/std_stack.i @@ -13,13 +13,13 @@ %define %std_stack_methods(stack...) stack(); - stack( const _Sequence& ); + stack(const _Sequence& other); bool empty() const; size_type size() const; const value_type& top() const; void pop(); - void push( const value_type& ); + void push(const value_type& value); %enddef %define %std_stack_methods_val(stack...) @@ -121,7 +121,7 @@ namespace std { %swig_stack_methods_val(std::stack< _Tp*, _Sequence >); #endif - %std_stack_methods_val(std::stack< _Tp*, _Sequence >); + %std_stack_methods_val(stack); }; } diff --git a/Lib/std/std_streambuf.i b/Lib/std/std_streambuf.i index 7efb19c6c..e17249135 100644 --- a/Lib/std/std_streambuf.i +++ b/Lib/std/std_streambuf.i @@ -81,7 +81,7 @@ namespace std { basic_streambuf(); private: - basic_streambuf(const basic_streambuf&); + basic_streambuf(const basic_streambuf& other); }; } diff --git a/Lib/std/std_unordered_map.i b/Lib/std/std_unordered_map.i index 1cb714821..1fd1eb980 100644 --- a/Lib/std/std_unordered_map.i +++ b/Lib/std/std_unordered_map.i @@ -1,15 +1,11 @@ // // std::unordered_map -// Work in progress - the code is not compilable yet: -// operator--() and constructor(compare function) not available for unordered_ -// types // - %include %include %define %std_unordered_map_methods_common(unordered_map...) - %std_container_methods(unordered_map); + %std_container_methods_without_reverse_iterators(unordered_map); size_type erase(const key_type& x); size_type count(const key_type& x) const; @@ -22,8 +18,6 @@ } iterator find(const key_type& x); - iterator lower_bound(const key_type& x); - iterator upper_bound(const key_type& x); #endif %enddef @@ -68,7 +62,7 @@ namespace std { - template, + template, class _Pred = std::equal_to< _Key >, class _Alloc = allocator > > class unordered_map { public: @@ -77,11 +71,12 @@ namespace std { typedef _Key key_type; typedef _Tp mapped_type; typedef std::pair< const _Key, _Tp > value_type; - typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; + typedef _Hash hasher; + typedef _Compare key_equal; typedef _Alloc allocator_type; %traits_swigtype(_Key); @@ -101,26 +96,24 @@ namespace std { } } - %fragment(SWIG_Traits_frag(std::unordered_map< _Key, _Tp, _Compare, _Alloc >), "header", + %fragment(SWIG_Traits_frag(std::unordered_map< _Key, _Tp, _Hash, _Pred, _Alloc >), "header", fragment=SWIG_Traits_frag(std::pair< _Key, _Tp >), - fragment="StdMapTraits") { + fragment="StdUnorderedMapTraits") { namespace swig { - template <> struct traits > { + template <> struct traits > { typedef pointer_category category; static const char* type_name() { - return "std::unordered_map<" #_Key "," #_Tp "," #_Compare "," #_Alloc " >"; + return "std::unordered_map<" #_Key "," #_Tp "," #_Hash "," #_Pred "," #_Alloc " >"; } }; } } - %typemap_traits_ptr(SWIG_TYPECHECK_MAP, std::unordered_map< _Key, _Tp, _Compare, _Alloc >); - - unordered_map( const _Compare& ); + %typemap_traits_ptr(SWIG_TYPECHECK_MAP, std::unordered_map< _Key, _Tp, _Hash, _Pred, _Alloc >); #ifdef %swig_unordered_map_methods // Add swig/language extra methods - %swig_unordered_map_methods(std::unordered_map< _Key, _Tp, _Compare, _Alloc >); + %swig_unordered_map_methods(std::unordered_map< _Key, _Tp, _Hash, _Pred, _Alloc >); #endif %std_unordered_map_methods(unordered_map); diff --git a/Lib/std/std_unordered_multimap.i b/Lib/std/std_unordered_multimap.i index 46b56d88a..4be6aa492 100644 --- a/Lib/std/std_unordered_multimap.i +++ b/Lib/std/std_unordered_multimap.i @@ -1,15 +1,11 @@ // // std::unordered_multimap -// Work in progress - the code is not compilable yet: -// operator--() and constructor(compare function) not available for unordered_ -// types // %include - %define %std_unordered_multimap_methods(mmap...) - %std_map_methods_common(mmap); + %std_unordered_map_methods_common(mmap); #ifdef SWIG_EXPORT_ITERATOR_METHODS std::pair equal_range(const key_type& x); @@ -44,7 +40,7 @@ namespace std { - template, + template, class _Pred = std::equal_to< _Key >, class _Alloc = allocator > > class unordered_multimap { public: @@ -53,36 +49,35 @@ namespace std { typedef _Key key_type; typedef _Tp mapped_type; typedef std::pair< const _Key, _Tp > value_type; - typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; + typedef _Hash hasher; + typedef _Compare key_equal; typedef _Alloc allocator_type; %traits_swigtype(_Key); %traits_swigtype(_Tp); - %fragment(SWIG_Traits_frag(std::unordered_multimap< _Key, _Tp, _Compare, _Alloc >), "header", + %fragment(SWIG_Traits_frag(std::unordered_multimap< _Key, _Tp, _Hash, _Pred, _Alloc >), "header", fragment=SWIG_Traits_frag(std::pair< _Key, _Tp >), - fragment="StdMultimapTraits") { + fragment="StdUnorderedMultimapTraits") { namespace swig { - template <> struct traits > { + template <> struct traits > { typedef pointer_category category; static const char* type_name() { - return "std::unordered_multimap<" #_Key "," #_Tp "," #_Compare "," #_Alloc " >"; + return "std::unordered_multimap<" #_Key "," #_Tp "," #_Hash "," #_Pred "," #_Alloc " >"; } }; } } - %typemap_traits_ptr(SWIG_TYPECHECK_MULTIMAP, std::unordered_multimap< _Key, _Tp, _Compare, _Alloc >); + %typemap_traits_ptr(SWIG_TYPECHECK_MULTIMAP, std::unordered_multimap< _Key, _Tp, _Hash, _Pred, _Alloc >); - unordered_multimap( const _Compare& ); - #ifdef %swig_unordered_multimap_methods // Add swig/language extra methods - %swig_unordered_multimap_methods(std::unordered_multimap< _Key, _Tp, _Compare, _Alloc >); + %swig_unordered_multimap_methods(std::unordered_multimap< _Key, _Tp, _Hash, _Pred, _Alloc >); #endif %std_unordered_multimap_methods(unordered_multimap); diff --git a/Lib/std/std_unordered_multiset.i b/Lib/std/std_unordered_multiset.i index 725ca2fe7..2910fb6ff 100644 --- a/Lib/std/std_unordered_multiset.i +++ b/Lib/std/std_unordered_multiset.i @@ -1,8 +1,5 @@ // // std::unordered_multiset -// Work in progress - the code is not compilable yet: -// operator--() and constructor(compare function) not available for unordered_ -// types // %include @@ -20,19 +17,19 @@ // const declarations are used to guess the intent of the function being // exported; therefore, the following rationale is applied: // -// -- f(std::unordered_multiset), f(const std::unordered_multiset&): +// -- f(std::unordered_multiset), f(const std::unordered_multiset&): // the parameter being read-only, either a sequence or a -// previously wrapped std::unordered_multiset can be passed. -// -- f(std::unordered_multiset&), f(std::unordered_multiset*): +// previously wrapped std::unordered_multiset can be passed. +// -- f(std::unordered_multiset&), f(std::unordered_multiset*): // the parameter may be modified; therefore, only a wrapped std::unordered_multiset // can be passed. -// -- std::unordered_multiset f(), const std::unordered_multiset& f(): -// the set is returned by copy; therefore, a sequence of T:s +// -- std::unordered_multiset f(), const std::unordered_multiset& f(): +// the set is returned by copy; therefore, a sequence of Key:s // is returned which is most easily used in other functions -// -- std::unordered_multiset& f(), std::unordered_multiset* f(): +// -- std::unordered_multiset& f(), std::unordered_multiset* f(): // the set is returned by reference; therefore, a wrapped std::unordered_multiset // is returned -// -- const std::unordered_multiset* f(), f(const std::unordered_multiset*): +// -- const std::unordered_multiset* f(), f(const std::unordered_multiset*): // for consistency, they expect and return a plain set pointer. // ------------------------------------------------------------------------ @@ -43,8 +40,10 @@ namespace std { //unordered_multiset - template , - class _Alloc = allocator< _Key > > + template , + class _Compare = std::equal_to< _Key >, + class _Alloc = allocator< _Key > > class unordered_multiset { public: typedef size_t size_type; @@ -55,30 +54,30 @@ namespace std { typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; + typedef _Hash hasher; + typedef _Compare key_equal; typedef _Alloc allocator_type; %traits_swigtype(_Key); - %fragment(SWIG_Traits_frag(std::unordered_multiset< _Key, _Compare, _Alloc >), "header", + %fragment(SWIG_Traits_frag(std::unordered_multiset< _Key, _Hash, _Compare, _Alloc >), "header", fragment=SWIG_Traits_frag(_Key), - fragment="StdMultisetTraits") { + fragment="StdUnorderedMultisetTraits") { namespace swig { - template <> struct traits > { + template <> struct traits > { typedef pointer_category category; static const char* type_name() { - return "std::unordered_multiset<" #_Key "," #_Compare "," #_Alloc " >"; + return "std::unordered_multiset<" #_Key "," #_Hash "," #_Compare "," #_Alloc " >"; } }; } } - %typemap_traits_ptr(SWIG_TYPECHECK_MULTISET, std::unordered_multiset< _Key, _Compare, _Alloc >); - - unordered_multiset( const _Compare& ); + %typemap_traits_ptr(SWIG_TYPECHECK_MULTISET, std::unordered_multiset< _Key, _Hash, _Compare, _Alloc >); #ifdef %swig_unordered_multiset_methods // Add swig/language extra methods - %swig_unordered_multiset_methods(std::unordered_multiset< _Key, _Compare, _Alloc >); + %swig_unordered_multiset_methods(std::unordered_multiset< _Key, _Hash, _Compare, _Alloc >); #endif %std_unordered_multiset_methods(unordered_multiset); diff --git a/Lib/std/std_unordered_set.i b/Lib/std/std_unordered_set.i index 98e792040..91e807423 100644 --- a/Lib/std/std_unordered_set.i +++ b/Lib/std/std_unordered_set.i @@ -1,8 +1,5 @@ // // std::unordered_set -// Work in progress - the code is not compilable yet: -// operator--() and constructor(compare function) not available for unordered_ -// types // %include @@ -11,7 +8,7 @@ // Unordered Set %define %std_unordered_set_methods_common(unordered_set...) unordered_set(); - unordered_set( const unordered_set& ); + unordered_set(const unordered_set& other); bool empty() const; size_type size() const; @@ -53,19 +50,19 @@ // const declarations are used to guess the intent of the function being // exported; therefore, the following rationale is applied: // -// -- f(std::unordered_set), f(const std::unordered_set&): +// -- f(std::unordered_set), f(const std::unordered_set&): // the parameter being read-only, either a sequence or a -// previously wrapped std::unordered_set can be passed. -// -- f(std::unordered_set&), f(std::unordered_set*): +// previously wrapped std::unordered_set can be passed. +// -- f(std::unordered_set&), f(std::unordered_set*): // the parameter may be modified; therefore, only a wrapped std::unordered_set // can be passed. -// -- std::unordered_set f(), const std::unordered_set& f(): -// the unordered_set is returned by copy; therefore, a sequence of T:s +// -- std::unordered_set f(), const std::unordered_set& f(): +// the unordered_set is returned by copy; therefore, a sequence of Key:s // is returned which is most easily used in other functions -// -- std::unordered_set& f(), std::unordered_set* f(): +// -- std::unordered_set& f(), std::unordered_set* f(): // the unordered_set is returned by reference; therefore, a wrapped std::unordered_set // is returned -// -- const std::unordered_set* f(), f(const std::unordered_set*): +// -- const std::unordered_set* f(), f(const std::unordered_set*): // for consistency, they expect and return a plain unordered_set pointer. // ------------------------------------------------------------------------ @@ -77,20 +74,22 @@ namespace std { - template , + template , class _Compare = std::equal_to< _Key >, - class _Alloc = allocator< _Key > > + class _Alloc = allocator< _Key > > class unordered_set { public: typedef size_t size_type; typedef ptrdiff_t difference_type; - typedef _Hash hasher; typedef _Key value_type; typedef _Key key_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; + typedef _Hash hasher; + typedef _Compare key_equal; typedef _Alloc allocator_type; %traits_swigtype(_Key); @@ -110,8 +109,6 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_SET, std::unordered_set< _Key, _Hash, _Compare, _Alloc >); - unordered_set( const _Compare& ); - #ifdef %swig_unordered_set_methods // Add swig/language extra methods %swig_unordered_set_methods(std::unordered_set< _Key, _Hash, _Compare, _Alloc >); diff --git a/Lib/std/std_vector.i b/Lib/std/std_vector.i index 2c78b0eb9..ec1c7dad9 100644 --- a/Lib/std/std_vector.i +++ b/Lib/std/std_vector.i @@ -64,8 +64,8 @@ namespace std { typedef _Tp value_type; typedef value_type* pointer; typedef const value_type* const_pointer; - typedef _Tp& reference; - typedef const _Tp& const_reference; + typedef value_type& reference; + typedef const value_type& const_reference; typedef _Alloc allocator_type; #ifndef SWIGC @@ -103,13 +103,13 @@ namespace std { template class vector< _Tp*, _Alloc > { public: - typedef size_t size_type; + typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Tp* value_type; typedef value_type* pointer; typedef const value_type* const_pointer; - typedef value_type reference; - typedef value_type const_reference; + typedef value_type& reference; + typedef const value_type& const_reference; typedef _Alloc allocator_type; #ifndef SWIGC @@ -145,13 +145,13 @@ namespace std { template class vector< _Tp const *, _Alloc > { public: - typedef size_t size_type; + typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Tp const * value_type; typedef value_type* pointer; typedef const value_type* const_pointer; - typedef value_type reference; - typedef value_type const_reference; + typedef value_type& reference; + typedef const value_type& const_reference; typedef _Alloc allocator_type; #ifndef SWIGC @@ -188,13 +188,13 @@ namespace std { template class vector { public: - typedef size_t size_type; + typedef size_t size_type; typedef ptrdiff_t difference_type; typedef bool value_type; typedef value_type* pointer; typedef const value_type* const_pointer; - typedef value_type reference; - typedef value_type const_reference; + typedef value_type& reference; + typedef bool const_reference; typedef _Alloc allocator_type; #ifndef SWIGC diff --git a/Lib/std_except.i b/Lib/std_except.i index a4a7a85ac..0f8b23e70 100644 --- a/Lib/std_except.i +++ b/Lib/std_except.i @@ -19,11 +19,12 @@ * a new std_except.i file in the target library directory. * ----------------------------------------------------------------------------- */ -#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGGUILE) || defined(SWIGUTL) || defined(SWIGD) +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGGUILE) || defined(SWIGUTL) || defined(SWIGD) || defined(SWIGOCAML) #error "This version of std_except.i should not be used" #endif %{ +#include #include %} @@ -40,6 +41,7 @@ %enddef namespace std { + %std_exception_map(bad_cast, SWIG_TypeError); %std_exception_map(bad_exception, SWIG_SystemError); %std_exception_map(domain_error, SWIG_ValueError); %std_exception_map(exception, SWIG_SystemError); diff --git a/Lib/swig.swg b/Lib/swig.swg index 6f48f0d20..6dc215dcf 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -309,11 +309,13 @@ static int NAME(TYPE x) { %define %$classname %$ismember,"match$parentNode$name" %enddef %define %$isnested "match$nested"="1" %enddef + /* ----------------------------------------------------------------------------- - * Include all the warnings labels and macros + * Common includes for warning labels, macros, fragments etc * ----------------------------------------------------------------------------- */ %include +%include /* ----------------------------------------------------------------------------- * Overloading support diff --git a/Lib/swigfragments.swg b/Lib/swigfragments.swg new file mode 100644 index 000000000..2cbef7cce --- /dev/null +++ b/Lib/swigfragments.swg @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------------- + * swigfragments.swg + * + * Common fragments + * ----------------------------------------------------------------------------- */ + +/* ----------------------------------------------------------------------------- + * Fragments for C header files + * ----------------------------------------------------------------------------- */ + +%fragment("", "header") %{ +#include +%} + +/* Default compiler options for gcc allow long_long but not LLONG_MAX. + * Define SWIG_NO_LLONG_MAX if this added limits support is not wanted. */ +%fragment("", "header") %{ +#include +#if !defined(SWIG_NO_LLONG_MAX) +# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) +# define LLONG_MAX __LONG_LONG_MAX__ +# define LLONG_MIN (-LLONG_MAX - 1LL) +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +# endif +#endif +%} + +%fragment("", "header") %{ +#include +%} + +%fragment("", "header") %{ +#include +%} + +%fragment("", "header") %{ +#include +#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__BORLANDC__) || defined(_WATCOM) +# ifndef snprintf +# define snprintf _snprintf +# endif +#endif +%} + +%fragment("", "header") %{ +#include +#ifdef _MSC_VER +# ifndef strtoull +# define strtoull _strtoui64 +# endif +# ifndef strtoll +# define strtoll _strtoi64 +# endif +#endif +%} + +%fragment("", "header") %{ +#include +#include +#ifndef WCHAR_MIN +# define WCHAR_MIN 0 +#endif +#ifndef WCHAR_MAX +# define WCHAR_MAX 65535 +#endif +%} + +/* ----------------------------------------------------------------------------- + * Fragments for C++ header files + * ----------------------------------------------------------------------------- */ + +%fragment("", "header") %{ +#include +%} + +%fragment("", "header") %{ +#include +%} + +%fragment("", "header") %{ +#include +%} + +%fragment("", "header") %{ +#include +%} diff --git a/Lib/swiginit.swg b/Lib/swiginit.swg index cb72c36eb..33926b10f 100644 --- a/Lib/swiginit.swg +++ b/Lib/swiginit.swg @@ -98,7 +98,7 @@ SWIG_InitializeModule(void *clientdata) { /* Now work on filling in swig_module.types */ #ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: size %d\n", swig_module.size); + printf("SWIG_InitializeModule: size %lu\n", (unsigned long)swig_module.size); #endif for (i = 0; i < swig_module.size; ++i) { swig_type_info *type = 0; @@ -106,7 +106,7 @@ SWIG_InitializeModule(void *clientdata) { swig_cast_info *cast; #ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); + printf("SWIG_InitializeModule: type %lu %s\n", (unsigned long)i, swig_module.type_initial[i]->name); #endif /* if there is another module already loaded */ @@ -182,7 +182,7 @@ SWIG_InitializeModule(void *clientdata) { for (i = 0; i < swig_module.size; ++i) { int j = 0; swig_cast_info *cast = swig_module.cast_initial[i]; - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); + printf("SWIG_InitializeModule: type %lu %s\n", (unsigned long)i, swig_module.type_initial[i]->name); while (cast->type) { printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); cast++; diff --git a/Lib/swigrun.swg b/Lib/swigrun.swg index 1ef676187..59118ecad 100644 --- a/Lib/swigrun.swg +++ b/Lib/swigrun.swg @@ -43,6 +43,7 @@ /* Flags for pointer conversions */ #define SWIG_POINTER_DISOWN 0x1 #define SWIG_CAST_NEW_MEMORY 0x2 +#define SWIG_POINTER_NO_NULL 0x4 /* Flags for new pointer objects */ #define SWIG_POINTER_OWN 0x1 diff --git a/Lib/tcl/cni.i b/Lib/tcl/cni.i deleted file mode 100644 index 10a1403a2..000000000 --- a/Lib/tcl/cni.i +++ /dev/null @@ -1,2 +0,0 @@ -%include -%include diff --git a/Lib/tcl/jstring.i b/Lib/tcl/jstring.i deleted file mode 100644 index 7fb7b89fe..000000000 --- a/Lib/tcl/jstring.i +++ /dev/null @@ -1,42 +0,0 @@ -%include - -%fragment(SWIG_AsVal_frag(jstring),"header") { -SWIGINTERN int -SWIG_AsVal_dec(jstring)(Tcl_Obj * obj, jstring *val) -{ - int len = 0; - const char *cstr = Tcl_GetStringFromObj(obj, &len); - if (!cstr || (strcmp(cstr,"NULL") == 0)) { - if (val) *val = 0; - return SWIG_OK; - } else { - int len = 0; - const Tcl_UniChar *ucstr = Tcl_GetUnicodeFromObj(obj,&len); - if (val) { - *val = JvNewString((const jchar*)ucstr, len); - } - } - - return SWIG_NEWOBJ; -} -} - -%fragment(SWIG_From_frag(jstring),"header") { -SWIGINTERNINLINE Tcl_Obj * -SWIG_From_dec(jstring)(jstring val) -{ - if (!val) { - return Tcl_NewStringObj("NULL",-1); - } else { - return Tcl_NewUnicodeObj((Tcl_UniChar *)JvGetStringChars(val),JvGetStringUTFLength(val)); - } -} -} - -%typemaps_asvalfrom(%checkcode(STRING), - %arg(SWIG_AsVal(jstring)), - %arg(SWIG_From(jstring)), - %arg(SWIG_AsVal_frag(jstring)), - %arg(SWIG_From_frag(jstring)), - java::lang::String *); - diff --git a/Lib/tcl/mactkinit.c b/Lib/tcl/mactkinit.c index 78391d445..8d1420088 100644 --- a/Lib/tcl/mactkinit.c +++ b/Lib/tcl/mactkinit.c @@ -42,7 +42,7 @@ short SIOUXHandleOneEvent _ANSI_ARGS_((EventRecord *event)); * * MacintoshInit -- * - * This procedure calls Mac specific initilization calls. Most of + * This procedure calls Mac specific initialization calls. Most of * these calls must be made as soon as possible in the startup * process. * @@ -64,7 +64,7 @@ MacintoshInit() /* * Tk needs us to set the qd pointer it uses. This is needed - * so Tk doesn't have to assume the availablity of the qd global + * so Tk doesn't have to assume the availiblity of the qd global * variable. Which in turn allows Tk to be used in code resources. */ tcl_macQdPtr = &qd; @@ -124,7 +124,7 @@ MacintoshInit() * * SetupMainInterp -- * - * This procedure calls initalization routines require a Tcl + * This procedure calls initialization routines require a Tcl * interp as an argument. This call effectively makes the passed * iterpreter the "main" interpreter for the application. * @@ -133,7 +133,7 @@ MacintoshInit() * application should probably fail. * * Side effects: - * More initilization. + * More initialization. * *---------------------------------------------------------------------- */ diff --git a/Lib/tcl/std_map.i b/Lib/tcl/std_map.i index ade2b0ad1..2c7f40ac7 100644 --- a/Lib/tcl/std_map.i +++ b/Lib/tcl/std_map.i @@ -19,22 +19,28 @@ namespace std { - template class map { + template > class map { // add typemaps here public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef K key_type; typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + map(); - map(const map &); + map(const map& other); unsigned int size() const; bool empty() const; void clear(); %extend { const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) return i->second; else @@ -44,14 +50,14 @@ namespace std { (*self)[key] = x; } void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); if (i != self->end()) self->erase(i); else throw std::out_of_range("key not found"); } bool has_key(const K& key) { - std::map::iterator i = self->find(key); + std::map< K, T, C >::iterator i = self->find(key); return i != self->end(); } } diff --git a/Lib/tcl/std_pair.i b/Lib/tcl/std_pair.i index 1448d6524..39ef008d3 100644 --- a/Lib/tcl/std_pair.i +++ b/Lib/tcl/std_pair.i @@ -18,12 +18,14 @@ namespace std { template struct pair { + typedef T first_type; + typedef U second_type; pair(); pair(T first, U second); - pair(const pair& p); + pair(const pair& other); - template pair(const pair &p); + template pair(const pair &other); T first; U second; diff --git a/Lib/tcl/std_vector.i b/Lib/tcl/std_vector.i index 3fc0fd61d..5fba5379f 100644 --- a/Lib/tcl/std_vector.i +++ b/Lib/tcl/std_vector.i @@ -208,9 +208,17 @@ namespace std { } public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + vector(unsigned int size = 0); vector(unsigned int size, const T& value); - vector(const vector< T > &); + vector(const vector& other); unsigned int size() const; bool empty() const; @@ -359,9 +367,17 @@ namespace std { } public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + vector(unsigned int size = 0); vector(unsigned int size, const T& value); - vector(const vector< T > &); + vector(const vector& other); unsigned int size() const; bool empty() const; diff --git a/Lib/tcl/stl.i b/Lib/tcl/stl.i index 40c7584ec..04f86014f 100644 --- a/Lib/tcl/stl.i +++ b/Lib/tcl/stl.i @@ -2,7 +2,6 @@ * stl.i * ----------------------------------------------------------------------------- */ -/* initial STL definition. extended as needed in each language */ %include %include %include diff --git a/Lib/tcl/tclapi.swg b/Lib/tcl/tclapi.swg index 33dc324d4..2187de52e 100644 --- a/Lib/tcl/tclapi.swg +++ b/Lib/tcl/tclapi.swg @@ -16,7 +16,7 @@ extern "C" { /* Constant information structure */ typedef struct swig_const_info { int type; - char *name; + const char *name; long lvalue; double dvalue; void *pvalue; diff --git a/Lib/tcl/tclrun.swg b/Lib/tcl/tclrun.swg index fd1052a28..9010b9c87 100644 --- a/Lib/tcl/tclrun.swg +++ b/Lib/tcl/tclrun.swg @@ -125,7 +125,8 @@ SWIG_Tcl_ConvertPtrFromString(Tcl_Interp *interp, const char *c, void **ptr, swi /* Pointer values must start with leading underscore */ while (*c != '_') { *ptr = (void *) 0; - if (strcmp(c,"NULL") == 0) return SWIG_OK; + if (strcmp(c,"NULL") == 0) + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; /* Empty string: not a pointer */ if (*c == 0) return SWIG_ERROR; @@ -199,7 +200,7 @@ SWIG_Tcl_PointerTypeFromString(char *c) { return c; } -/* Convert a packed value value */ +/* Convert a packed pointer value */ SWIGRUNTIME int SWIG_Tcl_ConvertPacked(Tcl_Interp *SWIGUNUSEDPARM(interp) , Tcl_Obj *obj, void *ptr, int sz, swig_type_info *ty) { swig_cast_info *tc; @@ -225,15 +226,14 @@ SWIG_Tcl_ConvertPacked(Tcl_Interp *SWIGUNUSEDPARM(interp) , Tcl_Obj *obj, void * /* Take a pointer and convert it to a string */ SWIGRUNTIME void -SWIG_Tcl_MakePtr(char *c, void *ptr, swig_type_info *ty, int flags) { +SWIG_Tcl_MakePtr(char *c, void *ptr, swig_type_info *ty, int SWIGUNUSEDPARM(flags)) { if (ptr) { *(c++) = '_'; c = SWIG_PackData(c,&ptr,sizeof(void *)); strcpy(c,ty->name); } else { - strcpy(c,(char *)"NULL"); + strcpy(c,"NULL"); } - flags = 0; } /* Create a new pointer object */ @@ -287,14 +287,15 @@ SWIG_Tcl_SetModule(Tcl_Interp *interp, swig_module_info *module) { } /* -----------------------------------------------------------------------------* - * Object auxiliars + * Object auxiliaries * -----------------------------------------------------------------------------*/ SWIGRUNTIME void SWIG_Tcl_ObjectDelete(ClientData clientData) { swig_instance *si = (swig_instance *) clientData; - if ((si) && (si->destroy) && (SWIG_Disown(si->thisvalue))) { + if (!si) return; + if (si->destroy && SWIG_Disown(si->thisvalue)) { if (si->classptr->destructor) { (si->classptr->destructor)(si->thisvalue); } @@ -344,7 +345,6 @@ SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_ } cls_stack[cls_stack_top] = inst->classptr; cls_stack_bi[cls_stack_top] = -1; - cls = inst->classptr; while (1) { Tcl_HashEntry* hashentry; bi = cls_stack_bi[cls_stack_top]; diff --git a/Lib/typemaps/cstrings.swg b/Lib/typemaps/cstrings.swg index 7fe6a3f8f..0aca61101 100644 --- a/Lib/typemaps/cstrings.swg +++ b/Lib/typemaps/cstrings.swg @@ -203,7 +203,7 @@ * This macro is used to return Character data along with a size * parameter. * - * %cstring_output_maxsize(Char *outx, int *max) { + * %cstring_output_withsize(Char *outx, int *max) { * void foo(Char *outx, int *max) { * sprintf(outx,"blah blah\n"); * *max = strlen(outx); @@ -236,7 +236,7 @@ * This macro is used to return Character data that was * allocated with new or malloc. * - * %cstring_output_allocated(Char **outx, free($1)); + * %cstring_output_allocate(Char **outx, free($1)); * void foo(Char **outx) { * *outx = (Char *) malloc(512); * sprintf(outx,"blah blah\n"); @@ -263,7 +263,7 @@ * This macro is used to return Character data that was * allocated with new or malloc. * - * %cstring_output_allocated(Char **outx, int *sz, free($1)); + * %cstring_output_allocate_size(Char **outx, int *sz, free($1)); * void foo(Char **outx, int *sz) { * *outx = (Char *) malloc(512); * sprintf(outx,"blah blah\n"); diff --git a/Lib/typemaps/fragments.swg b/Lib/typemaps/fragments.swg index 048fd34d3..e83f415c4 100644 --- a/Lib/typemaps/fragments.swg +++ b/Lib/typemaps/fragments.swg @@ -96,83 +96,34 @@ * common fragments * ------------------------------------------------------------ */ -/* Default compiler options for gcc allow long_long but not LLONG_MAX. - * Define SWIG_NO_LLONG_MAX if this added limits support is not wanted. */ -%fragment("","header") %{ -#include -#if !defined(SWIG_NO_LLONG_MAX) -# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) -# define LLONG_MAX __LONG_LONG_MAX__ -# define LLONG_MIN (-LLONG_MAX - 1LL) -# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) -# endif -#endif -%} - -%fragment("","header") %{ -#include -%} - -%fragment("","header") %{ -#include -#include -#ifndef WCHAR_MIN -# define WCHAR_MIN 0 -#endif -#ifndef WCHAR_MAX -# define WCHAR_MAX 65535 -#endif -%} - -%fragment("","header") %{ -#include -%} - -%fragment("","header") %{ -#include -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) -# ifndef snprintf -# define snprintf _snprintf -# endif -#endif -%} - -%fragment("","header") %{ -#include -#ifdef _MSC_VER -# ifndef strtoull -# define strtoull _strtoui64 -# endif -# ifndef strtoll -# define strtoll _strtoi64 -# endif -#endif -%} - -%fragment("", "header") %{ -#include -%} - -%fragment("", "header") %{ -#include -%} - -%fragment("", "header") %{ -#include -%} - -%fragment("", "header") %{ -#include -%} - %fragment("SWIG_isfinite","header",fragment=",") %{ /* Getting isfinite working pre C99 across multiple platforms is non-trivial. Users can provide SWIG_isfinite on older platforms. */ #ifndef SWIG_isfinite -/* isfinite() is a macro for C99, but a function in namespace std for C++11. */ +/* isfinite() is a macro for C99 */ # if defined(isfinite) # define SWIG_isfinite(X) (isfinite(X)) -# elif defined __cplusplus && __cplusplus >= 201103L -# define SWIG_isfinite(X) (std::isfinite(X)) +# elif defined(__cplusplus) && __cplusplus >= 201103L +/* Use a template so that this works whether isfinite() is std::isfinite() or + * in the global namespace. The reality seems to vary between compiler + * versions. + * + * Make sure namespace std exists to avoid compiler warnings. + * + * extern "C++" is required as this fragment can end up inside an extern "C" { } block + */ +namespace std { } +extern "C++" template +inline int SWIG_isfinite_func(T x) { + using namespace std; + return isfinite(x); +} +# define SWIG_isfinite(X) (SWIG_isfinite_func(X)) +# elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) +# define SWIG_isfinite(X) (__builtin_isfinite(X)) +# elif defined(__clang__) && defined(__has_builtin) +# if __has_builtin(__builtin_isfinite) +# define SWIG_isfinite(X) (__builtin_isfinite(X)) +# endif # elif defined(_MSC_VER) # define SWIG_isfinite(X) (_finite(X)) # elif defined(__sun) && defined(__SVR4) diff --git a/Lib/typemaps/std_except.swg b/Lib/typemaps/std_except.swg index cb5ed3050..75d066490 100644 --- a/Lib/typemaps/std_except.swg +++ b/Lib/typemaps/std_except.swg @@ -20,6 +20,7 @@ %enddef namespace std { + %std_exception_map(bad_cast, SWIG_TypeError); %std_exception_map(bad_exception, SWIG_SystemError); %std_exception_map(domain_error, SWIG_ValueError); %std_exception_map(exception, SWIG_SystemError); diff --git a/Lib/typemaps/string.swg b/Lib/typemaps/string.swg index 1bf0bd15a..4b7072365 100644 --- a/Lib/typemaps/string.swg +++ b/Lib/typemaps/string.swg @@ -18,7 +18,7 @@ SWIG_pchar_descriptor(void) } %fragment("SWIG_strnlen","header",fragment="SWIG_FromCharPtrAndSize") { -size_t +SWIGINTERN size_t SWIG_strnlen(const char* s, size_t maxlen) { const char *p; diff --git a/Lib/typemaps/swigmacros.swg b/Lib/typemaps/swigmacros.swg index 61470583e..687b0680e 100644 --- a/Lib/typemaps/swigmacros.swg +++ b/Lib/typemaps/swigmacros.swg @@ -31,7 +31,7 @@ %as_voidptrptr(a) reinterpret_cast(a) or their C unsafe versions. In C++ we use the safe version unless - SWIG_NO_CPLUSPLUS_CAST is defined (usually via the -nocppcast swig flag). + SWIG_NO_CPLUSPLUS_CAST is defined Memory allocation: @@ -43,7 +43,7 @@ %new_instance(Type) Allocate a new instance of given Type %new_copy(value,Type) Allocate and initialize a new instance with 'value' - %new_array(size,Type) Allocate a new array with given size and Type + %new_array(size,Type) Allocate a new array with given size and Type and zero initialize %new_copy_array(cptr,size,Type) Allocate and initialize a new array from 'cptr' %delete(cptr) Delete an instance %delete_array(cptr) Delete an array @@ -123,14 +123,7 @@ nocppval * Casting operators * ----------------------------------------------------------------------------- */ -#if defined(SWIG_NO_CPLUSPLUS_CAST) -/* Disable 'modern' cplusplus casting operators */ -# if defined(SWIG_CPLUSPLUS_CAST) -# undef SWIG_CPLUSPLUS_CAST -# endif -#endif - -#if defined(__cplusplus) && defined(SWIG_CPLUSPLUS_CAST) +#if defined(__cplusplus) && !defined(SWIG_NO_CPLUSPLUS_CAST) # define %const_cast(a,Type...) const_cast< Type >(a) # define %static_cast(a,Type...) static_cast< Type >(a) # define %reinterpret_cast(a,Type...) reinterpret_cast< Type >(a) @@ -157,17 +150,17 @@ nocppval * ----------------------------------------------------------------------------- */ #if defined(__cplusplus) -# define %new_instance(Type...) (new Type) +# define %new_instance(Type...) (new Type()) # define %new_copy(val,Type...) (new Type(%static_cast(val, const Type&))) -# define %new_array(size,Type...) (new Type[size]) -# define %new_copy_array(ptr,size,Type...) %reinterpret_cast(memcpy(%new_array(size,Type), ptr, sizeof(Type)*(size)), Type*) +# define %new_array(size,Type...) (new Type[size]()) +# define %new_copy_array(ptr,size,Type...) %reinterpret_cast(memcpy(new Type[size], ptr, sizeof(Type)*(size)), Type*) # define %delete(cptr) delete cptr # define %delete_array(cptr) delete[] cptr #else /* C case */ -# define %new_instance(Type...) (Type *)malloc(sizeof(Type)) +# define %new_instance(Type...) (Type *)calloc(1,sizeof(Type)) # define %new_copy(val,Type...) (Type *)memcpy(%new_instance(Type),&val,sizeof(Type)) -# define %new_array(size,Type...) (Type *)malloc((size)*sizeof(Type)) -# define %new_copy_array(ptr,size,Type...) (Type *)memcpy(%new_array(size,Type), ptr, sizeof(Type)*(size)) +# define %new_array(size,Type...) (Type *)calloc(size, sizeof(Type)) +# define %new_copy_array(ptr,size,Type...) (Type *)memcpy(malloc((size)*sizeof(Type)), ptr, sizeof(Type)*(size)) # define %delete(cptr) free((char*)cptr) # define %delete_array(cptr) free((char*)cptr) #endif /* __cplusplus */ diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg index d3633eb49..581de1a90 100644 --- a/Lib/typemaps/swigtype.swg +++ b/Lib/typemaps/swigtype.swg @@ -358,46 +358,46 @@ %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) SWIGTYPE & { void *vptr = 0; - int res = SWIG_ConvertPtr($input, &vptr, $descriptor, 0); + int res = SWIG_ConvertPtr($input, &vptr, $descriptor, SWIG_POINTER_NO_NULL); $1 = SWIG_CheckState(res); } %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) SWIGTYPE && { void *vptr = 0; - int res = SWIG_ConvertPtr($input, &vptr, $descriptor, 0); + int res = SWIG_ConvertPtr($input, &vptr, $descriptor, SWIG_POINTER_NO_NULL); $1 = SWIG_CheckState(res); } #if defined(__cplusplus) && defined(%implicitconv_flag) %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1,implicitconv=1) const SWIGTYPE & { - int res = SWIG_ConvertPtr($input, 0, $descriptor, %implicitconv_flag); + int res = SWIG_ConvertPtr($input, 0, $descriptor, SWIG_POINTER_NO_NULL | %implicitconv_flag); $1 = SWIG_CheckState(res); } %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1,implicitconv=1) const SWIGTYPE && { - int res = SWIG_ConvertPtr($input, 0, $descriptor, %implicitconv_flag); + int res = SWIG_ConvertPtr($input, 0, $descriptor, SWIG_POINTER_NO_NULL | %implicitconv_flag); $1 = SWIG_CheckState(res); } %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1,implicitconv=1) SWIGTYPE { - int res = SWIG_ConvertPtr($input, 0, $&descriptor, %implicitconv_flag); + int res = SWIG_ConvertPtr($input, 0, $&descriptor, SWIG_POINTER_NO_NULL | %implicitconv_flag); $1 = SWIG_CheckState(res); } #else %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) const SWIGTYPE & { void *vptr = 0; - int res = SWIG_ConvertPtr($input, &vptr, $descriptor, 0); + int res = SWIG_ConvertPtr($input, &vptr, $descriptor, SWIG_POINTER_NO_NULL); $1 = SWIG_CheckState(res); } %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) const SWIGTYPE && { void *vptr = 0; - int res = SWIG_ConvertPtr($input, &vptr, $descriptor, 0); + int res = SWIG_ConvertPtr($input, &vptr, $descriptor, SWIG_POINTER_NO_NULL); $1 = SWIG_CheckState(res); } %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) SWIGTYPE { void *vptr = 0; - int res = SWIG_ConvertPtr($input, &vptr, $&descriptor, 0); + int res = SWIG_ConvertPtr($input, &vptr, $&descriptor, SWIG_POINTER_NO_NULL); $1 = SWIG_CheckState(res); } #endif @@ -410,12 +410,16 @@ /* directorin */ -%typemap(directorin,noblock=1) SWIGTYPE *, SWIGTYPE *const& { +%typemap(directorin,noblock=1) SWIGTYPE { + $input = SWIG_NewPointerObj(%as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags); +} + +%typemap(directorin,noblock=1) SWIGTYPE * { $input = SWIG_NewPointerObj(%as_voidptr($1), $descriptor, %newpointer_flags); } -%typemap(directorin,noblock=1) SWIGTYPE { - $input = SWIG_NewPointerObj(%as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags); +%typemap(directorin,noblock=1) SWIGTYPE *const& { + $input = SWIG_NewPointerObj(%as_voidptr($1), $*descriptor, %newpointer_flags); } %typemap(directorin,noblock=1) SWIGTYPE & { @@ -427,6 +431,7 @@ } /* directorout */ + #if defined(__cplusplus) && defined(%implicitconv_flag) %typemap(directorout,noblock=1,implicitconv=1) SWIGTYPE (void * swig_argp, int swig_res = 0) { swig_res = SWIG_ConvertPtr($input,&swig_argp,$&descriptor, %convertptr_flags | %implicitconv_flag); @@ -461,6 +466,22 @@ } } +%typemap(directorout,noblock=1,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) + SWIGTYPE *const&(void *swig_argp, int swig_res, swig_owntype own) { + swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $*descriptor, %convertptr_flags | SWIG_POINTER_DISOWN, &own); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res,"$type"); + } + $1_ltype swig_temp = new $*1_ltype(($*1_ltype)swig_argp); + swig_acquire_ownership(swig_temp); + $result = swig_temp; +} +%typemap(directorfree,noblock=1,match="directorout") SWIGTYPE *const& { + if (director) { + SWIG_AcquirePtr($result, director->swig_release_ownership(%as_voidptr(*$input))); + } +} + %typemap(directorout,noblock=1,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE &(void *swig_argp, int swig_res, swig_owntype own) { swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor, %convertptr_flags | SWIG_POINTER_DISOWN, &own); @@ -584,6 +605,9 @@ } #endif +%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) } +%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) } + /* ------------------------------------------------------------ * --- function ptr typemaps --- * ------------------------------------------------------------ */ @@ -645,6 +669,8 @@ } #endif +%apply SWIGTYPE ((*)(ANY)) { SWIGTYPE ((* const)(ANY)) } + %apply SWIGTYPE * { SWIGTYPE *const } /* ------------------------------------------------------------ diff --git a/Lib/typemaps/wstring.swg b/Lib/typemaps/wstring.swg index 1f2de8221..cd409d1ce 100644 --- a/Lib/typemaps/wstring.swg +++ b/Lib/typemaps/wstring.swg @@ -19,7 +19,7 @@ SWIG_pwchar_descriptor() } %fragment("SWIG_wcsnlen","header",fragment="SWIG_FromWCharPtrAndSize") { -size_t +SWIGINTERN size_t SWIG_wcsnlen(const wchar_t* s, size_t maxlen) { const wchar_t *p; diff --git a/Lib/windows.i b/Lib/windows.i index 2c093dacc..3e4626196 100644 --- a/Lib/windows.i +++ b/Lib/windows.i @@ -112,6 +112,9 @@ typedef unsigned __int64 DWORD64, *PDWORD64; // Types from winnt.h typedef void *PVOID; typedef void *PVOID64; +#ifndef VOID +#define VOID void +#endif typedef char CHAR; typedef short SHORT; typedef long LONG; diff --git a/Makefile.in b/Makefile.in index 26f9730b0..e529f14c4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -69,15 +69,8 @@ skip-ruby = test -n "@SKIP_RUBY@" skip-php = test -n "@SKIP_PHP@" skip-ocaml = test -n "@SKIP_OCAML@" skip-octave = test -n "@SKIP_OCTAVE@" -skip-pike = test -n "@SKIP_PIKE@" -skip-chicken = test -n "@SKIP_CHICKEN@" skip-csharp = test -n "@SKIP_CSHARP@" -skip-modula3 = test -n "@SKIP_MODULA3@" skip-lua = test -n "@SKIP_LUA@" -skip-allegrocl = test -n "@SKIP_ALLEGROCL@" -skip-clisp = test -n "@SKIP_CLISP@" -skip-cffi = test -n "@SKIP_CFFI@" -skip-uffi = test -n "@SKIP_UFFI@" skip-r = test -n "@SKIP_R@" skip-c = test -n "@SKIP_C@" skip-scilab = test -n "@SKIP_SCILAB@" @@ -86,7 +79,6 @@ skip-d = test -n "@SKIP_D@" skip-javascript = test -n "@SKIP_JAVASCRIPT@" # Additional dependencies for some tests -skip-gcj = test -n "@SKIP_GCJ@" skip-android = test -n "@SKIP_ANDROID@" # Special errors test-case @@ -118,15 +110,8 @@ check-aliveness: @$(skip-ruby) || ./$(TARGET) -ruby -help @$(skip-ocaml) || ./$(TARGET) -ocaml -help @$(skip-octave) || ./$(TARGET) -octave -help - @$(skip-php) || ./$(TARGET) -php -help - @$(skip-pike) || ./$(TARGET) -pike -help - @$(skip-chicken) || ./$(TARGET) -chicken -help + @$(skip-php) || ./$(TARGET) -php7 -help @$(skip-csharp) || ./$(TARGET) -csharp -help - @$(skip-modula3) || ./$(TARGET) -modula3 -help - @$(skip-allegrocl)|| ./$(TARGET) -allegrocl -help - @$(skip-clisp) || ./$(TARGET) -clisp -help - @$(skip-uffi) || ./$(TARGET) -uffi -help - @$(skip-cffi) || ./$(TARGET) -cffi -help @$(skip-lua) || ./$(TARGET) -lua -help @$(skip-r) || ./$(TARGET) -r -help @$(skip-c) || ./$(TARGET) -c -help @@ -152,15 +137,8 @@ check-versions: \ check-ocaml-version \ check-octave-version \ check-php-version \ - check-pike-version \ - check-chicken-version \ check-csharp-version \ - check-modula3-version \ check-lua-version \ - check-allegrocl-version \ - check-clisp-version \ - check-uffi-version \ - check-cffi-version \ check-r-version \ check-scilab-version \ check-go-version \ @@ -192,15 +170,8 @@ check-examples: \ check-ocaml-examples \ check-octave-examples \ check-php-examples \ - check-pike-examples \ - check-chicken-examples \ check-csharp-examples \ - check-modula3-examples \ check-lua-examples \ - check-allegrocl-examples \ - check-clisp-examples \ - check-uffi-examples \ - check-cffi-examples \ check-r-examples \ check-c-examples \ check-scilab-examples \ @@ -219,15 +190,8 @@ ruby_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/ruby/check.list) ocaml_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/ocaml/check.list) octave_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/octave/check.list) php_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/php/check.list) -pike_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/pike/check.list) -chicken_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/chicken/check.list) csharp_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/csharp/check.list) -modula3_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/modula3/check.list) lua_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/lua/check.list) -allegrocl_examples := -clisp_examples := -uffi_examples := -cffi_examples := r_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/r/check.list) c_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/c/check.list) scilab_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/scilab/check.list) @@ -255,16 +219,6 @@ check-%-examples : @echo $(ACTION)ing Examples/$(LANGUAGE)/$* @(cd Examples/$(LANGUAGE)/$* && $(MAKE) $(FLAGS) $(ACTION) RUNPIPE=$(RUNPIPE)) -# gcj individual example -java.actionexample: - @cd Examples && $(MAKE) Makefile - @if $(skip-gcj); then \ - echo "skipping Examples/$(LANGUAGE)/java $(ACTION) (gcj test)"; \ - else \ - echo $(ACTION)ing Examples/$(LANGUAGE)/java; \ - (cd Examples/$(LANGUAGE)/java && $(MAKE) $(FLAGS) $(ACTION) RUNPIPE=$(RUNPIPE)) \ - fi - # Checks testcases in the test-suite excluding those which are known to be broken check-test-suite: \ check-errors-test-suite \ @@ -278,15 +232,8 @@ check-test-suite: \ check-ocaml-test-suite \ check-octave-test-suite \ check-php-test-suite \ - check-pike-test-suite \ check-csharp-test-suite \ - check-modula3-test-suite \ check-lua-test-suite \ - check-allegrocl-test-suite \ - check-clisp-test-suite \ - check-uffi-test-suite \ - check-cffi-test-suite \ - check-chicken-test-suite \ check-r-test-suite \ check-c-test-suite \ check-scilab-test-suite \ @@ -333,15 +280,8 @@ all-test-suite: \ all-ocaml-test-suite \ all-octave-test-suite \ all-php-test-suite \ - all-pike-test-suite \ all-csharp-test-suite \ - all-modula3-test-suite \ all-lua-test-suite \ - all-allegrocl-test-suite \ - all-clisp-test-suite \ - all-uffi-test-suite \ - all-cffi-test-suite \ - all-chicken-test-suite \ all-r-test-suite \ all-c-test-suite \ all-scilab-test-suite \ @@ -364,15 +304,8 @@ broken-test-suite: \ broken-ocaml-test-suite \ broken-octave-test-suite \ broken-php-test-suite \ - broken-pike-test-suite \ broken-csharp-test-suite \ - broken-modula3-test-suite \ broken-lua-test-suite \ - broken-allegrocl-test-suite \ - broken-clisp-test-suite \ - broken-uffi-test-suite \ - broken-cffi-test-suite \ - broken-chicken-test-suite \ broken-r-test-suite \ broken-c-test-suite \ broken-scilab-test-suite \ @@ -486,7 +419,7 @@ check-maintainer-clean: maintainer-clean $(srcdir)/Lib/swigwarn.swg: $(srcdir)/Source/Include/swigwarn.h mkdir -p Lib - echo "/* SWIG warning codes */" > $@ + echo "/* SWIG warning codes - generated from swigwarn.h - do not edit */" > $@ cat $? | grep "^#define WARN\|/\*.*\*/\|^[ \t]*$$" | sed 's/^#define \(WARN.*[0-9][0-9]*\)\(.*\)$$/%define SWIG\1 %enddef\2/' >> $@ ##################################################################### @@ -509,9 +442,9 @@ install-main: @echo "Installing $(DESTDIR)$(BIN_DIR)/`echo $(TARGET_NOEXE) | sed '$(transform)'`@EXEEXT@" @$(INSTALL_PROGRAM) $(TARGET) $(DESTDIR)$(BIN_DIR)/`echo $(TARGET_NOEXE) | sed '$(transform)'`@EXEEXT@ -lib-languages = gcj typemaps tcl perl5 python guile java mzscheme ruby php ocaml octave \ - pike chicken csharp modula3 allegrocl clisp lua cffi uffi r c go d javascript javascript/jsc \ - javascript/v8 scilab +lib-languages = typemaps tcl perl5 python guile java mzscheme ruby php ocaml octave \ + csharp lua r c go d javascript javascript/jsc \ + javascript/v8 scilab xml lib-modules = std @@ -593,9 +526,9 @@ srcrpm: # version 1.10 for our case of not having a top level Makefile.am. Until then we # can fetch them manually and will have to commit them to Git. configfiles: - wget ftp://ftp.gnu.org/pub/gnu/config/config.guess -O Tools/config/config.guess + wget 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess' -O Tools/config/config.guess chmod a+x Tools/config/config.guess - wget ftp://ftp.gnu.org/pub/gnu/config/config.sub -O Tools/config/config.sub + wget 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub' -O Tools/config/config.sub chmod a+x Tools/config/config.sub # Regenerate Makefile if Makefile.in or config.status have changed. diff --git a/README b/README index 3421b72bf..165098cb5 100644 --- a/README +++ b/README @@ -1,13 +1,11 @@ SWIG (Simplified Wrapper and Interface Generator) -Version: 3.0.11 (in progress) +Version: 4.0.1 (in progress) Tagline: SWIG is a compiler that integrates C and C++ with languages including Perl, Python, Tcl, Ruby, PHP, Java, C#, D, Go, Lua, - Octave, R, Scheme (Guile, MzScheme/Racket, CHICKEN), Scilab, - Ocaml, Modula-3, Common Lisp (CLISP, Allegro CL, CFFI, UFFI) - and Pike. SWIG can also export its parse tree into XML and - Lisp s-expressions. + Octave, R, Scheme (Guile, MzScheme/Racket), Scilab, Ocaml. + SWIG can also export its parse tree into XML. SWIG reads annotated C/C++ header files and creates wrapper code (glue code) in order to make the corresponding C/C++ libraries available to @@ -20,7 +18,7 @@ Up-to-date SWIG related information can be found at A SWIG FAQ and other hints can be found on the SWIG Wiki: - http://www.dabeaz.com/cgi-bin/wiki.pl + https://github.com/swig/swig/wiki License ======= @@ -126,7 +124,7 @@ installed. To fix this: have to do this. If you are having other troubles, you might look at the SWIG Wiki at -http://www.dabeaz.com/cgi-bin/wiki.pl. +https://github.com/swig/swig/wiki. Participate! ============ diff --git a/RELEASENOTES b/RELEASENOTES index 080bb6066..3fe78f2e2 100644 --- a/RELEASENOTES +++ b/RELEASENOTES @@ -7,6 +7,46 @@ Release Notes Detailed release notes are available with the release and are also published on the SWIG web site at http://swig.org/release.html. +SWIG-4.0.0 summary: +- Support for Doxygen documentation comments which are parsed and + converted into JavaDoc or PyDoc comments. +- STL wrappers improved for C#, Java and Ruby. +- C++11 STL containers added for Java, Python and Ruby. +- Improved support for parsing C++11 and C++14 code. +- Various fixes for shared_ptr. +- Various C preprocessor corner case fixes. +- Corner case fixes for member function pointers. +- Python module overhaul by simplifying the generated code and turning + most optimizations on by default. +- %template improvements wrt scoping to align with C++ explicit + template instantiations. +- Added support for a command-line options file (sometimes called a + response file). +- Numerous enhancements and fixes for all supported target languages. +- SWIG now classifies the status of target languages into either + 'Experimental' or 'Supported' to indicate the expected maturity + level. +- Support for CFFI, Allegrocl, Chicken, CLISP, S-EXP, UFFI, Pike, + Modula3 has been removed. +- Octave 4.4-5.1 support added. +- PHP5 support removed, PHP7 is now the supported PHP version. +- Minimum Python version required is now 2.7, 3.2-3.7 are the only + other versions supported. +- Added support for Javascript NodeJS versions 2-10. +- OCaml support is much improved and updated, minimum OCaml version + required is now 3.12.0. + +SWIG-3.0.12 summary: +- Add support for Octave-4.2. +- Enhance %extend to support template functions. +- Language specific enhancements and fixes for C#, D, Guile, Java, PHP7. + +SWIG-3.0.11 summary: +- PHP 7 support added. +- C++11 alias templates and type aliasing support added. +- Minor fixes and enhancements for C# Go Guile Java Javascript Octave + PHP Python R Ruby Scilab XML. + SWIG-3.0.10 summary: - Regression fixes for smart pointers and importing Python modules. diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h index ab5f74b19..c67ffeaba 100644 --- a/Source/CParse/cparse.h +++ b/Source/CParse/cparse.h @@ -28,6 +28,7 @@ extern "C" { extern int cparse_cplusplusout; extern int cparse_start_line; extern String *cparse_unknown_directive; + extern int scan_doxygen_comments; extern void Swig_cparse_cplusplus(int); extern void Swig_cparse_cplusplusout(int); @@ -61,7 +62,7 @@ extern "C" { extern void cparse_normalize_void(Node *); extern Parm *Swig_cparse_parm(String *s); extern ParmList *Swig_cparse_parms(String *s, Node *file_line_node); - extern Node *new_node(const_String_or_char_ptr tag); + extern Node *Swig_cparse_new_node(const_String_or_char_ptr tag); /* templ.c */ extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope); @@ -78,4 +79,7 @@ extern "C" { #define SWIG_WARN_NODE_END(Node) \ if (wrnfilter) Swig_warnfilter(wrnfilter,0); \ } + +#define COMPOUND_EXPR_VAL(dtype) \ + ((dtype).type == T_CHAR || (dtype).type == T_WCHAR ? (dtype).rawval : (dtype).val) #endif diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 637ac9d60..4566817a0 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -50,6 +50,57 @@ static int last_brace = 0; static int last_id = 0; static int rename_active = 0; +/* Doxygen comments scanning */ +int scan_doxygen_comments = 0; + +int isStructuralDoxygen(String *s) { + static const char* const structuralTags[] = { + "addtogroup", + "callgraph", + "callergraph", + "category", + "def", + "defgroup", + "dir", + "example", + "file", + "headerfile", + "internal", + "mainpage", + "name", + "nosubgrouping", + "overload", + "package", + "page", + "protocol", + "relates", + "relatesalso", + "showinitializer", + "weakgroup", + }; + + unsigned n; + char *slashPointer = Strchr(s, '\\'); + char *atPointer = Strchr(s,'@'); + if (slashPointer == NULL && atPointer == NULL) + return 0; + else if(slashPointer == NULL) + slashPointer = atPointer; + + slashPointer++; /* skip backslash or at sign */ + + for (n = 0; n < sizeof(structuralTags)/sizeof(structuralTags[0]); n++) { + const size_t len = strlen(structuralTags[n]); + if (strncmp(slashPointer, structuralTags[n], len) == 0) { + /* Take care to avoid false positives with prefixes of other tags. */ + if (slashPointer[len] == '\0' || isspace(slashPointer[len])) + return 1; + } + } + + return 0; +} + /* ----------------------------------------------------------------------------- * Swig_cparse_cplusplus() * ----------------------------------------------------------------------------- */ @@ -367,10 +418,70 @@ static int yylook(void) { case SWIG_TOKEN_COMMENT: { - String *cmt = Scanner_text(scan); - char *loc = Char(cmt); - if ((strncmp(loc,"/*@SWIG",7) == 0) && (loc[Len(cmt)-3] == '@')) { - Scanner_locator(scan, cmt); + typedef enum { + DOX_COMMENT_PRE = -1, + DOX_COMMENT_NONE, + DOX_COMMENT_POST + } comment_kind_t; + comment_kind_t existing_comment = DOX_COMMENT_NONE; + + /* Concatenate or skip all consecutive comments at once. */ + do { + String *cmt = Scanner_text(scan); + char *loc = Char(cmt); + if ((strncmp(loc, "/*@SWIG", 7) == 0) && (loc[Len(cmt)-3] == '@')) { + Scanner_locator(scan, cmt); + } + if (scan_doxygen_comments) { /* else just skip this node, to avoid crashes in parser module*/ + /* Check for all possible Doxygen comment start markers while ignoring + comments starting with a row of asterisks or slashes just as + Doxygen itself does. */ + if (Len(cmt) > 3 && loc[0] == '/' && + ((loc[1] == '/' && ((loc[2] == '/' && loc[3] != '/') || loc[2] == '!')) || + (loc[1] == '*' && ((loc[2] == '*' && loc[3] != '*') || loc[2] == '!')))) { + comment_kind_t this_comment = loc[3] == '<' ? DOX_COMMENT_POST : DOX_COMMENT_PRE; + if (existing_comment != DOX_COMMENT_NONE && this_comment != existing_comment) { + /* We can't concatenate together Doxygen pre- and post-comments. */ + break; + } + + if (this_comment == DOX_COMMENT_POST || !isStructuralDoxygen(loc)) { + String *str; + + int begin = this_comment == DOX_COMMENT_POST ? 4 : 3; + int end = Len(cmt); + if (loc[end - 1] == '/' && loc[end - 2] == '*') { + end -= 2; + } + + str = NewStringWithSize(loc + begin, end - begin); + + if (existing_comment == DOX_COMMENT_NONE) { + yylval.str = str; + Setline(yylval.str, Scanner_start_line(scan)); + Setfile(yylval.str, Scanner_file(scan)); + } else { + Append(yylval.str, str); + } + + existing_comment = this_comment; + } + } + } + do { + tok = Scanner_token(scan); + } while (tok == SWIG_TOKEN_ENDLINE); + } while (tok == SWIG_TOKEN_COMMENT); + + Scanner_pushtoken(scan, tok, Scanner_text(scan)); + + switch (existing_comment) { + case DOX_COMMENT_PRE: + return DOXYGENSTRING; + case DOX_COMMENT_NONE: + break; + case DOX_COMMENT_POST: + return DOXYGENPOSTSTRING; } } break; @@ -907,6 +1018,8 @@ int yylex(void) { return (ID); case POUND: return yylex(); + case SWIG_TOKEN_COMMENT: + return yylex(); default: return (l); } diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 784187c28..08c92b9cf 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -57,12 +57,20 @@ static Node *currentOuterClass = 0; /* for nested classes */ static const char *last_cpptype = 0; static int inherit_list = 0; static Parm *template_parameters = 0; +static int parsing_template_declaration = 0; static int extendmode = 0; static int compact_default_args = 0; static int template_reduce = 0; static int cparse_externc = 0; int ignore_nested_classes = 0; int kwargs_supported = 0; +/* ----------------------------------------------------------------------------- + * Doxygen Comment Globals + * ----------------------------------------------------------------------------- */ +static String *currentDeclComment = NULL; /* Comment of C/C++ declaration. */ +static Node *previousNode = NULL; /* Pointer to the previous node (for post comments) */ +static Node *currentNode = NULL; /* Pointer to the current node (for post comments) */ + /* ----------------------------------------------------------------------------- * Assist Functions * ----------------------------------------------------------------------------- */ @@ -74,6 +82,14 @@ static void yyerror (const char *e) { (void)e; } +static Node *new_node(const_String_or_char_ptr tag) { + Node *n = Swig_cparse_new_node(tag); + /* Remember the previous node in case it will need a post-comment */ + previousNode = currentNode; + currentNode = n; + return n; +} + /* Copies a node. Does not copy tree links or symbol table data (except for sym:name) */ @@ -150,6 +166,11 @@ static Node *copy_node(Node *n) { Setattr(nn, "needs_defaultargs", "1"); continue; } + /* same for abstracts, which contains pointers to the source node children, and so will need to be patch too */ + if (strcmp(ckey,"abstracts") == 0) { + SetFlag(nn, "needs_abstracts"); + continue; + } /* Looks okay. Just copy the data using Copy */ ci = Copy(k.item); Setattr(nn, key, ci); @@ -158,6 +179,36 @@ static Node *copy_node(Node *n) { return nn; } +static void set_comment(Node *n, String *comment) { + String *name; + Parm *p; + if (!n || !comment) + return; + + if (Getattr(n, "doxygen")) + Append(Getattr(n, "doxygen"), comment); + else { + Setattr(n, "doxygen", comment); + /* This is the first comment, populate it with @params, if any */ + p = Getattr(n, "parms"); + while (p) { + if (Getattr(p, "doxygen")) + Printv(comment, "\n@param ", Getattr(p, "name"), Getattr(p, "doxygen"), NIL); + p=nextSibling(p); + } + } + + /* Append same comment to every generated overload */ + name = Getattr(n, "name"); + if (!name) + return; + n = nextSibling(n); + while (n && Getattr(n, "name") && Strcmp(Getattr(n, "name"), name) == 0) { + Setattr(n, "doxygen", comment); + n = nextSibling(n); + } +} + /* ----------------------------------------------------------------------------- * Variables * ----------------------------------------------------------------------------- */ @@ -193,7 +244,7 @@ int SWIG_cparse_template_reduce(int treduce) { * ----------------------------------------------------------------------------- */ static int promote_type(int t) { - if (t <= T_UCHAR || t == T_CHAR) return T_INT; + if (t <= T_UCHAR || t == T_CHAR || t == T_WCHAR) return T_INT; return t; } @@ -208,7 +259,7 @@ static String *yyrename = 0; /* Forward renaming operator */ -static String *resolve_create_node_scope(String *cname); +static String *resolve_create_node_scope(String *cname, int is_class_definition); Hash *Swig_cparse_features(void) { @@ -262,6 +313,7 @@ static String *add_oldname = 0; static String *make_name(Node *n, String *name,SwigType *decl) { + String *made_name = 0; int destructor = name && (*(Char(name)) == '~'); if (yyrename) { @@ -275,7 +327,13 @@ static String *make_name(Node *n, String *name,SwigType *decl) { } if (!name) return 0; - return Swig_name_make(n,Namespaceprefix,name,decl,add_oldname); + + if (parsing_template_declaration) + SetFlag(n, "parsing_template_declaration"); + made_name = Swig_name_make(n, Namespaceprefix, name, decl, add_oldname); + Delattr(n, "parsing_template_declaration"); + + return made_name; } /* Generate an unnamed identifier */ @@ -364,7 +422,8 @@ static void add_symbols(Node *n) { } if (extendmode) { - Setattr(n,"isextendmember","1"); + if (!Getattr(n, "template")) + SetFlag(n,"isextendmember"); } if (!isfriend && inclass) { @@ -440,7 +499,10 @@ static void add_symbols(Node *n) { symname = Copy(Getattr(n,"unnamed")); } if (symname) { + if (parsing_template_declaration) + SetFlag(n, "parsing_template_declaration"); wrn = Swig_name_warning(n, Namespaceprefix, symname,0); + Delattr(n, "parsing_template_declaration"); } } else { String *name = Getattr(n,"name"); @@ -453,7 +515,10 @@ static void add_symbols(Node *n) { Swig_features_get(Swig_cparse_features(),Namespaceprefix,name,fun,n); symname = make_name(n, name,fun); + if (parsing_template_declaration) + SetFlag(n, "parsing_template_declaration"); wrn = Swig_name_warning(n, Namespaceprefix,symname,fun); + Delattr(n, "parsing_template_declaration"); Delete(fdecl); Delete(fun); @@ -470,8 +535,19 @@ static void add_symbols(Node *n) { SetFlag(n,"deleted"); SetFlag(n,"feature:ignore"); } + if (SwigType_isrvalue_reference(Getattr(n, "refqualifier"))) { + /* Ignore rvalue ref-qualifiers by default + * Use Getattr instead of GetFlag to handle explicit ignore and explicit not ignore */ + if (!(Getattr(n, "feature:ignore") || Strncmp(symname, "$ignore", 7) == 0)) { + SWIG_WARN_NODE_BEGIN(n); + Swig_warning(WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED, Getfile(n), Getline(n), + "Method with rvalue ref-qualifier %s ignored.\n", Swig_name_decl(n)); + SWIG_WARN_NODE_END(n); + SetFlag(n, "feature:ignore"); + } + } } - if (only_csymbol || GetFlag(n,"feature:ignore") || strncmp(Char(symname),"$ignore",7) == 0) { + if (only_csymbol || GetFlag(n, "feature:ignore") || Strncmp(symname, "$ignore", 7) == 0) { /* Only add to C symbol table and continue */ Swig_symbol_add(0, n); if (!only_csymbol && !GetFlag(n, "feature:ignore")) { @@ -486,7 +562,7 @@ static void add_symbols(Node *n) { SetFlag(n, "feature:ignore"); } if (!GetFlag(n, "feature:ignore") && Strcmp(symname,"$ignore") == 0) { - /* Add feature:ignore if the symbol was explicitely ignored, regardless of visibility */ + /* Add feature:ignore if the symbol was explicitly ignored, regardless of visibility */ SetFlag(n, "feature:ignore"); } } else { @@ -717,6 +793,22 @@ static List *pure_abstracts(Node *n) { return abstracts; } +/* Recompute the "abstracts" attribute for the classes in instantiated templates, similarly to update_defaultargs() above. */ +static void update_abstracts(Node *n) { + for (; n; n = nextSibling(n)) { + Node* const child = firstChild(n); + if (!child) + continue; + + update_abstracts(child); + + if (Getattr(n, "needs_abstracts")) { + Setattr(n, "abstracts", pure_abstracts(child)); + Delattr(n, "needs_abstracts"); + } + } +} + /* Make a classname */ static String *make_class_name(String *name) { @@ -800,32 +892,53 @@ static String *remove_block(Node *kw, const String *inputcode) { return modified_code; } - +/* +#define RESOLVE_DEBUG 1 +*/ static Node *nscope = 0; static Node *nscope_inner = 0; /* Remove the scope prefix from cname and return the base name without the prefix. * The scopes required for the symbol name are resolved and/or created, if required. * For example AA::BB::CC as input returns CC and creates the namespace AA then inner - * namespace BB in the current scope. If cname is found to already exist as a weak symbol - * (forward reference) then the scope might be changed to match, such as when a symbol match - * is made via a using reference. */ -static String *resolve_create_node_scope(String *cname) { + * namespace BB in the current scope. */ +static String *resolve_create_node_scope(String *cname, int is_class_definition) { Symtab *gscope = 0; Node *cname_node = 0; - int skip_lookup = 0; + String *last = Swig_scopename_last(cname); nscope = 0; nscope_inner = 0; - if (Strncmp(cname,"::",2) == 0) - skip_lookup = 1; - - cname_node = skip_lookup ? 0 : Swig_symbol_clookup_no_inherit(cname, 0); + if (Strncmp(cname,"::" ,2) != 0) { + if (is_class_definition) { + /* Only lookup symbols which are in scope via a using declaration but not via a using directive. + For example find y via 'using x::y' but not y via a 'using namespace x'. */ + cname_node = Swig_symbol_clookup_no_inherit(cname, 0); + if (!cname_node) { + Node *full_lookup_node = Swig_symbol_clookup(cname, 0); + if (full_lookup_node) { + /* This finds a symbol brought into scope via both a using directive and a using declaration. */ + Node *last_node = Swig_symbol_clookup_no_inherit(last, 0); + if (last_node == full_lookup_node) + cname_node = last_node; + } + } + } else { + /* For %template, the template needs to be in scope via any means. */ + cname_node = Swig_symbol_clookup(cname, 0); + } + } +#if RESOLVE_DEBUG + if (!cname_node) + Printf(stdout, "symbol does not yet exist (%d): [%s]\n", is_class_definition, cname); + else + Printf(stdout, "symbol does exist (%d): [%s]\n", is_class_definition, cname); +#endif if (cname_node) { /* The symbol has been defined already or is in another scope. - If it is a weak symbol, it needs replacing and if it was brought into the current scope - via a using declaration, the scope needs adjusting appropriately for the new symbol. + If it is a weak symbol, it needs replacing and if it was brought into the current scope, + the scope needs adjusting appropriately for the new symbol. Similarly for defined templates. */ Symtab *symtab = Getattr(cname_node, "sym:symtab"); Node *sym_weak = Getattr(cname_node, "sym:weak"); @@ -833,48 +946,92 @@ static String *resolve_create_node_scope(String *cname) { /* Check if the scope is the current scope */ String *current_scopename = Swig_symbol_qualifiedscopename(0); String *found_scopename = Swig_symbol_qualifiedscopename(symtab); - int len; if (!current_scopename) current_scopename = NewString(""); if (!found_scopename) found_scopename = NewString(""); - len = Len(current_scopename); - if ((len > 0) && (Strncmp(current_scopename, found_scopename, len) == 0)) { - if (Len(found_scopename) > len + 2) { - /* A matching weak symbol was found in non-global scope, some scope adjustment may be required */ - String *new_cname = NewString(Char(found_scopename) + len + 2); /* skip over "::" prefix */ - String *base = Swig_scopename_last(cname); - Printf(new_cname, "::%s", base); - cname = new_cname; - Delete(base); - } else { - /* A matching weak symbol was found in the same non-global local scope, no scope adjustment required */ - assert(len == Len(found_scopename)); + + { + int fail = 1; + List *current_scopes = Swig_scopename_tolist(current_scopename); + List *found_scopes = Swig_scopename_tolist(found_scopename); + Iterator cit = First(current_scopes); + Iterator fit = First(found_scopes); +#if RESOLVE_DEBUG +Printf(stdout, "comparing current: [%s] found: [%s]\n", current_scopename, found_scopename); +#endif + for (; fit.item && cit.item; fit = Next(fit), cit = Next(cit)) { + String *current = cit.item; + String *found = fit.item; +#if RESOLVE_DEBUG + Printf(stdout, " looping %s %s\n", current, found); +#endif + if (Strcmp(current, found) != 0) + break; } - } else { - String *base = Swig_scopename_last(cname); - if (Len(found_scopename) > 0) { - /* A matching weak symbol was found in a different scope to the local scope - probably via a using declaration */ - cname = NewStringf("%s::%s", found_scopename, base); + + if (!cit.item) { + String *subscope = NewString(""); + for (; fit.item; fit = Next(fit)) { + if (Len(subscope) > 0) + Append(subscope, "::"); + Append(subscope, fit.item); + } + if (Len(subscope) > 0) + cname = NewStringf("%s::%s", subscope, last); + else + cname = Copy(last); +#if RESOLVE_DEBUG + Printf(stdout, "subscope to create: [%s] cname: [%s]\n", subscope, cname); +#endif + fail = 0; + Delete(subscope); } else { - /* Either: - 1) A matching weak symbol was found in a different scope to the local scope - this is actually a - symbol with the same name in a different scope which we don't want, so no adjustment required. - 2) A matching weak symbol was found in the global scope - no adjustment required. - */ - cname = Copy(base); + if (is_class_definition) { + if (!fit.item) { + /* It is valid to define a new class with the same name as one forward declared in a parent scope */ + fail = 0; + } else if (Swig_scopename_check(cname)) { + /* Classes defined with scope qualifiers must have a matching forward declaration in matching scope */ + fail = 1; + } else { + /* This may let through some invalid cases */ + fail = 0; + } +#if RESOLVE_DEBUG + Printf(stdout, "scope for class definition, fail: %d\n", fail); +#endif + } else { +#if RESOLVE_DEBUG + Printf(stdout, "no matching base scope for template\n"); +#endif + fail = 1; + } + } + + Delete(found_scopes); + Delete(current_scopes); + + if (fail) { + String *cname_resolved = NewStringf("%s::%s", found_scopename, last); + Swig_error(cparse_file, cparse_line, "'%s' resolves to '%s' and was incorrectly instantiated in scope '%s' instead of within scope '%s'.\n", cname, cname_resolved, current_scopename, found_scopename); + cname = Copy(last); + Delete(cname_resolved); } - Delete(base); } + Delete(current_scopename); Delete(found_scopename); } + } else if (!is_class_definition) { + /* A template instantiation requires a template to be found in scope... fail here too? + Swig_error(cparse_file, cparse_line, "No template found to instantiate '%s' with %%template.\n", cname); + */ } if (Swig_scopename_check(cname)) { Node *ns; String *prefix = Swig_scopename_prefix(cname); - String *base = Swig_scopename_last(cname); if (prefix && (Strncmp(prefix,"::",2) == 0)) { /* I don't think we can use :: global scope to declare classes and hence neither %template. - consider reporting error instead - wsfulton. */ /* Use the global scope */ @@ -884,6 +1041,7 @@ static String *resolve_create_node_scope(String *cname) { gscope = set_scope_to_global(); } if (Len(prefix) == 0) { + String *base = Copy(last); /* Use the global scope, but we need to add a 'global' namespace. */ if (!gscope) gscope = set_scope_to_global(); /* note that this namespace is not the "unnamed" one, @@ -892,6 +1050,7 @@ static String *resolve_create_node_scope(String *cname) { nscope = new_node("namespace"); Setattr(nscope,"symtab", gscope);; nscope_inner = nscope; + Delete(last); return base; } /* Try to locate the scope */ @@ -909,7 +1068,7 @@ static String *resolve_create_node_scope(String *cname) { String *nname = Swig_symbol_qualifiedscopename(nstab); if (tname && (Strcmp(tname,nname) == 0)) { ns = 0; - cname = base; + cname = Copy(last); } Delete(tname); Delete(nname); @@ -917,19 +1076,10 @@ static String *resolve_create_node_scope(String *cname) { if (ns) { /* we will try to create a new node using the namespaces we can find in the scope name */ - List *scopes; + List *scopes = Swig_scopename_tolist(prefix); String *sname; Iterator si; - String *name = NewString(prefix); - scopes = NewList(); - while (name) { - String *base = Swig_scopename_last(name); - String *tprefix = Swig_scopename_prefix(name); - Insert(scopes,0,base); - Delete(base); - Delete(name); - name = tprefix; - } + for (si = First(scopes); si.item; si = Next(si)) { Node *ns1,*ns2; sname = si.item; @@ -975,12 +1125,13 @@ static String *resolve_create_node_scope(String *cname) { nscope_inner = ns2; if (!nscope) nscope = ns2; } - cname = base; + cname = Copy(last); Delete(scopes); } } Delete(prefix); } + Delete(last); return cname; } @@ -1336,6 +1487,56 @@ static void mark_nodes_as_extend(Node *n) { } } +/* ----------------------------------------------------------------------------- + * add_qualifier_to_declarator() + * + * Normally the qualifier is pushed on to the front of the type. + * Adding a qualifier to a pointer to member function is a special case. + * For example : typedef double (Cls::*pmf)(void) const; + * The qualifier is : q(const). + * The declarator is : m(Cls).f(void). + * We need : m(Cls).q(const).f(void). + * ----------------------------------------------------------------------------- */ + +static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) { + int is_pointer_to_member_function = 0; + String *decl = Copy(type); + String *poppedtype = NewString(""); + assert(qualifier); + + while (decl) { + if (SwigType_ismemberpointer(decl)) { + String *memberptr = SwigType_pop(decl); + if (SwigType_isfunction(decl)) { + is_pointer_to_member_function = 1; + SwigType_push(decl, qualifier); + SwigType_push(decl, memberptr); + Insert(decl, 0, poppedtype); + Delete(memberptr); + break; + } else { + Append(poppedtype, memberptr); + } + Delete(memberptr); + } else { + String *popped = SwigType_pop(decl); + if (!popped) + break; + Append(poppedtype, popped); + Delete(popped); + } + } + + if (!is_pointer_to_member_function) { + Delete(decl); + decl = Copy(type); + SwigType_push(decl, qualifier); + } + + Delete(poppedtype); + return decl; +} + %} %union { @@ -1346,10 +1547,12 @@ static void mark_nodes_as_extend(Node *n) { String *rawval; int type; String *qualifier; + String *refqualifier; String *bitfield; Parm *throws; String *throwf; String *nexcept; + String *final; } dtype; struct { const char *type; @@ -1365,6 +1568,7 @@ static void mark_nodes_as_extend(Node *n) { ParmList *throws; String *throwf; String *nexcept; + String *final; } decl; Parm *tparms; struct { @@ -1417,6 +1621,9 @@ static void mark_nodes_as_extend(Node *n) { %token CONVERSIONOPERATOR %token PARSETYPE PARSEPARM PARSEPARMS +%token DOXYGENSTRING +%token DOXYGENPOSTSTRING + %left CAST %left QUESTIONMARK %left LOR @@ -1443,35 +1650,36 @@ static void mark_nodes_as_extend(Node *n) { /* C declarations */ %type c_declaration c_decl c_decl_tail c_enum_key c_enum_inherit c_enum_decl c_enum_forward_decl c_constructor_decl; -%type enumlist edecl; +%type enumlist enumlist_item edecl_with_dox edecl; /* C++ declarations */ %type cpp_declaration cpp_class_decl cpp_forward_class_decl cpp_template_decl cpp_alternate_rettype; -%type cpp_members cpp_member; +%type cpp_members cpp_member cpp_member_no_dox; %type cpp_constructor_decl cpp_destructor_decl cpp_protection_decl cpp_conversion_operator cpp_static_assert; -%type cpp_swig_directive cpp_temp_possible cpp_opt_declarators ; +%type cpp_swig_directive cpp_template_possible cpp_opt_declarators ; %type cpp_using_decl cpp_namespace_decl cpp_catch_decl cpp_lambda_decl; %type kwargs options; /* Misc */ %type identifier; -%type initializer cpp_const exception_specification; +%type initializer cpp_const exception_specification cv_ref_qualifier qualifiers_exception_specification; %type storage_class extern_string; %type parms ptail rawparms varargs_parms ; %type templateparameters templateparameterstail; -%type

    parm valparm rawvalparms valparms valptail ; +%type

    parm_no_dox parm valparm rawvalparms valparms valptail ; %type

    typemap_parm tm_list tm_tail ; %type

    templateparameter ; -%type templcpptype cpptype access_specifier; +%type templcpptype cpptype classkey classkeyopt access_specifier; %type base_specifier; %type ellipsis variadic; %type type rawtype type_right anon_bitfield_type decltype ; %type base_list inherit raw_inherit; %type definetype def_args etype default_delete deleted_definition explicit_default; -%type expr exprnum exprcompound valexpr; +%type expr exprnum exprcompound valexpr exprmem; %type ename ; %type less_valparms_greater; -%type type_qualifier ; +%type type_qualifier; +%type ref_qualifier; %type type_qualifier_raw; %type idstring idstringopt; %type pragma_lang; @@ -1491,8 +1699,7 @@ static void mark_nodes_as_extend(Node *n) { %type featattr; %type lambda_introducer lambda_body; %type lambda_tail; -%type optional_constant_directive; -%type virt_specifier_seq; +%type virt_specifier_seq virt_specifier_seq_opt; %% @@ -1538,9 +1745,24 @@ program : interface { interface : interface declaration { /* add declaration to end of linked list (the declaration isn't always a single declaration, sometimes it is a linked list itself) */ + if (currentDeclComment != NULL) { + set_comment($2, currentDeclComment); + currentDeclComment = NULL; + } appendChild($1,$2); $$ = $1; } + | interface DOXYGENSTRING { + currentDeclComment = $2; + $$ = $1; + } + | interface DOXYGENPOSTSTRING { + Node *node = lastChild($1); + if (node) { + set_comment(node, $2); + } + $$ = $1; + } | empty { $$ = new_node("top"); } @@ -1613,14 +1835,14 @@ swig_directive : extend_directive { $$ = $1; } %extend classname { ... } ------------------------------------------------------------ */ -extend_directive : EXTEND options idcolon LBRACE { +extend_directive : EXTEND options classkeyopt idcolon LBRACE { Node *cls; String *clsname; extendmode = 1; cplus_mode = CPLUS_PUBLIC; if (!classes) classes = NewHash(); if (!classes_typedefs) classes_typedefs = NewHash(); - clsname = make_class_name($3); + clsname = make_class_name($4); cls = Getattr(classes,clsname); if (!cls) { cls = Getattr(classes_typedefs, clsname); @@ -1629,7 +1851,7 @@ extend_directive : EXTEND options idcolon LBRACE { Node *am = Getattr(Swig_extend_hash(),clsname); if (!am) { Swig_symbol_newscope(); - Swig_symbol_setscopename($3); + Swig_symbol_setscopename($4); prev_symtab = 0; } else { prev_symtab = Swig_symbol_setscope(Getattr(am,"symtab")); @@ -1642,7 +1864,7 @@ extend_directive : EXTEND options idcolon LBRACE { prev_symtab = Swig_symbol_setscope(Getattr(cls, "symtab")); current_class = cls; SWIG_WARN_NODE_BEGIN(cls); - Swig_warning(WARN_PARSE_EXTEND_NAME, cparse_file, cparse_line, "Deprecated %%extend name used - the %s name '%s' should be used instead of the typedef name '%s'.\n", Getattr(cls, "kind"), SwigType_namestr(Getattr(cls, "name")), $3); + Swig_warning(WARN_PARSE_EXTEND_NAME, cparse_file, cparse_line, "Deprecated %%extend name used - the %s name '%s' should be used instead of the typedef name '%s'.\n", Getattr(cls, "kind"), SwigType_namestr(Getattr(cls, "name")), $4); SWIG_WARN_NODE_END(cls); } } else { @@ -1650,7 +1872,7 @@ extend_directive : EXTEND options idcolon LBRACE { prev_symtab = Swig_symbol_setscope(Getattr(cls,"symtab")); current_class = cls; } - Classprefix = NewString($3); + Classprefix = NewString($4); Namespaceprefix= Swig_symbol_qualifiedscopename(0); Delete(clsname); } cpp_members RBRACE { @@ -1662,22 +1884,22 @@ extend_directive : EXTEND options idcolon LBRACE { Swig_symbol_setscope(prev_symtab); } Namespaceprefix = Swig_symbol_qualifiedscopename(0); - clsname = make_class_name($3); + clsname = make_class_name($4); Setattr($$,"name",clsname); - mark_nodes_as_extend($6); + mark_nodes_as_extend($7); if (current_class) { /* We add the extension to the previously defined class */ - appendChild($$,$6); + appendChild($$, $7); appendChild(current_class,$$); } else { /* We store the extensions in the extensions hash */ Node *am = Getattr(Swig_extend_hash(),clsname); if (am) { /* Append the members to the previous extend methods */ - appendChild(am,$6); + appendChild(am, $7); } else { - appendChild($$,$6); + appendChild($$, $7); Setattr(Swig_extend_hash(),clsname,$$); } } @@ -1736,7 +1958,6 @@ constant_directive : CONSTANT identifier EQUAL definetype SEMI { } } - | CONSTANT type declarator def_args SEMI { if (($4.type != T_ERROR) && ($4.type != T_SYMBOL)) { SwigType_push($2,$3.type); @@ -1753,12 +1974,38 @@ constant_directive : CONSTANT identifier EQUAL definetype SEMI { SetFlag($$,"feature:immutable"); add_symbols($$); } else { - if ($4.type == T_ERROR) { - Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE,cparse_file,cparse_line,"Unsupported constant value\n"); - } + if ($4.type == T_ERROR) { + Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE,cparse_file,cparse_line, "Unsupported constant value\n"); + } $$ = 0; } } + /* Member function pointers with qualifiers. eg. + %constant short (Funcs::*pmf)(bool) const = &Funcs::F; */ + | CONSTANT type direct_declarator LPAREN parms RPAREN cv_ref_qualifier def_args SEMI { + if (($8.type != T_ERROR) && ($8.type != T_SYMBOL)) { + SwigType_add_function($2, $5); + SwigType_push($2, $7.qualifier); + SwigType_push($2, $3.type); + /* Sneaky callback function trick */ + if (SwigType_isfunction($2)) { + SwigType_add_pointer($2); + } + $$ = new_node("constant"); + Setattr($$, "name", $3.id); + Setattr($$, "type", $2); + Setattr($$, "value", $8.val); + if ($8.rawval) Setattr($$, "rawval", $8.rawval); + Setattr($$, "storage", "%constant"); + SetFlag($$, "feature:immutable"); + add_symbols($$); + } else { + if ($8.type == T_ERROR) { + Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE,cparse_file,cparse_line, "Unsupported constant value\n"); + } + $$ = 0; + } + } | CONSTANT error SEMI { Swig_warning(WARN_PARSE_BAD_VALUE,cparse_file,cparse_line,"Bad constant value (ignored).\n"); $$ = 0; @@ -2560,9 +2807,8 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va tscope = Swig_symbol_current(); /* Get the current scope */ /* If the class name is qualified, we need to create or lookup namespace entries */ - if (!inclass) { - $5 = resolve_create_node_scope($5); - } + $5 = resolve_create_node_scope($5, 0); + if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) { outer_class = nscope_inner; } @@ -2718,7 +2964,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va Swig_cparse_template_expand(templnode,nname,temparms,tscope); Setattr(templnode,"sym:name",nname); Delete(nname); - Setattr(templnode,"feature:onlychildren", "typemap,typemapitem,typemapcopy,typedef,types,fragment"); + Setattr(templnode,"feature:onlychildren", "typemap,typemapitem,typemapcopy,typedef,types,fragment,apply"); if ($3) { Swig_warning(WARN_PARSE_NESTED_TEMPLATE, cparse_file, cparse_line, "Named nested template instantiations not supported. Processing as if no name was given to %%template().\n"); } @@ -2833,6 +3079,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va nn = Getattr(nn,"sym:nextSibling"); /* repeat for overloaded templated functions. If a templated class there will never be a sibling. */ } update_defaultargs(linkliststart); + update_abstracts(linkliststart); } Swig_symbol_setscope(tscope); Delete(Namespaceprefix); @@ -2901,63 +3148,138 @@ c_declaration : c_decl { | USING idcolon EQUAL type plain_declarator SEMI { /* Convert using statement to a typedef statement */ $$ = new_node("cdecl"); - SwigType_push($4,$5.type); Setattr($$,"type",$4); Setattr($$,"storage","typedef"); Setattr($$,"name",$2); - Setattr($$,"decl",""); + Setattr($$,"decl",$5.type); SetFlag($$,"typealias"); add_symbols($$); } | TEMPLATE LESSTHAN template_parms GREATERTHAN USING idcolon EQUAL type plain_declarator SEMI { - $$ = new_node("using"); + /* Convert alias template to a "template" typedef statement */ + $$ = new_node("template"); + Setattr($$,"type",$8); + Setattr($$,"storage","typedef"); Setattr($$,"name",$6); - SwigType_push($8,$9.type); - Setattr($$,"uname",$8); + Setattr($$,"decl",$9.type); + Setattr($$,"templateparms",$3); + Setattr($$,"templatetype","cdecl"); + SetFlag($$,"aliastemplate"); add_symbols($$); - SWIG_WARN_NODE_BEGIN($$); - Swig_warning(WARN_CPP11_ALIAS_TEMPLATE, cparse_file, cparse_line, "The 'using' keyword in template aliasing is not fully supported yet.\n"); - SWIG_WARN_NODE_END($$); - - $$ = 0; /* TODO - ignored for now */ } + | cpp_static_assert { + $$ = $1; + } ; /* ------------------------------------------------------------ A C global declaration of some kind (may be variable, function, typedef, etc.) ------------------------------------------------------------ */ -c_decl : storage_class type declarator initializer c_decl_tail { +c_decl : storage_class type declarator cpp_const initializer c_decl_tail { + String *decl = $3.type; $$ = new_node("cdecl"); - if ($4.qualifier) SwigType_push($3.type,$4.qualifier); + if ($4.qualifier) + decl = add_qualifier_to_declarator($3.type, $4.qualifier); + Setattr($$,"refqualifier",$4.refqualifier); Setattr($$,"type",$2); Setattr($$,"storage",$1); Setattr($$,"name",$3.id); + Setattr($$,"decl",decl); + Setattr($$,"parms",$3.parms); + Setattr($$,"value",$5.val); + Setattr($$,"throws",$4.throws); + Setattr($$,"throw",$4.throwf); + Setattr($$,"noexcept",$4.nexcept); + Setattr($$,"final",$4.final); + if ($5.val && $5.type) { + /* store initializer type as it might be different to the declared type */ + SwigType *valuetype = NewSwigType($5.type); + if (Len(valuetype) > 0) + Setattr($$,"valuetype",valuetype); + else + Delete(valuetype); + } + if (!$6) { + if (Len(scanner_ccode)) { + String *code = Copy(scanner_ccode); + Setattr($$,"code",code); + Delete(code); + } + } else { + Node *n = $6; + /* Inherit attributes */ + while (n) { + String *type = Copy($2); + Setattr(n,"type",type); + Setattr(n,"storage",$1); + n = nextSibling(n); + Delete(type); + } + } + if ($5.bitfield) { + Setattr($$,"bitfield", $5.bitfield); + } + + if ($3.id) { + /* Look for "::" declarations (ignored) */ + if (Strstr($3.id, "::")) { + /* This is a special case. If the scope name of the declaration exactly + matches that of the declaration, then we will allow it. Otherwise, delete. */ + String *p = Swig_scopename_prefix($3.id); + if (p) { + if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) || + (Classprefix && Strcmp(p, Classprefix) == 0)) { + String *lstr = Swig_scopename_last($3.id); + Setattr($$, "name", lstr); + Delete(lstr); + set_nextSibling($$, $6); + } else { + Delete($$); + $$ = $6; + } + Delete(p); + } else { + Delete($$); + $$ = $6; + } + } else { + set_nextSibling($$, $6); + } + } else { + Swig_error(cparse_file, cparse_line, "Missing symbol name for global declaration\n"); + $$ = 0; + } + + if ($4.qualifier && $1 && Strstr($1, "static")) + Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$)); + } + /* Alternate function syntax introduced in C++11: + auto funcName(int x, int y) -> int; */ + | storage_class AUTO declarator cpp_const ARROW cpp_alternate_rettype virt_specifier_seq_opt initializer c_decl_tail { + $$ = new_node("cdecl"); + if ($4.qualifier) SwigType_push($3.type, $4.qualifier); + Setattr($$,"refqualifier",$4.refqualifier); + Setattr($$,"type",$6); + Setattr($$,"storage",$1); + Setattr($$,"name",$3.id); Setattr($$,"decl",$3.type); Setattr($$,"parms",$3.parms); Setattr($$,"value",$4.val); Setattr($$,"throws",$4.throws); Setattr($$,"throw",$4.throwf); Setattr($$,"noexcept",$4.nexcept); - if ($4.val && $4.type) { - /* store initializer type as it might be different to the declared type */ - SwigType *valuetype = NewSwigType($4.type); - if (Len(valuetype) > 0) - Setattr($$,"valuetype",valuetype); - else - Delete(valuetype); - } - if (!$5) { + Setattr($$,"final",$4.final); + if (!$9) { if (Len(scanner_ccode)) { String *code = Copy(scanner_ccode); Setattr($$,"code",code); Delete(code); } } else { - Node *n = $5; - /* Inherit attributes */ + Node *n = $9; while (n) { - String *type = Copy($2); + String *type = Copy($6); Setattr(n,"type",type); Setattr(n,"storage",$1); n = nextSibling(n); @@ -2968,10 +3290,7 @@ c_decl : storage_class type declarator initializer c_decl_tail { Setattr($$,"bitfield", $4.bitfield); } - /* Look for "::" declarations (ignored) */ if (Strstr($3.id,"::")) { - /* This is a special case. If the scope name of the declaration exactly - matches that of the declaration, then we will allow it. Otherwise, delete. */ String *p = Swig_scopename_prefix($3.id); if (p) { if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) || @@ -2979,75 +3298,22 @@ c_decl : storage_class type declarator initializer c_decl_tail { String *lstr = Swig_scopename_last($3.id); Setattr($$,"name",lstr); Delete(lstr); - set_nextSibling($$,$5); + set_nextSibling($$, $9); } else { Delete($$); - $$ = $5; + $$ = $9; } Delete(p); } else { Delete($$); - $$ = $5; + $$ = $9; } } else { - set_nextSibling($$,$5); - } - } - /* Alternate function syntax introduced in C++11: - auto funcName(int x, int y) -> int; */ - | storage_class AUTO declarator ARROW cpp_alternate_rettype initializer c_decl_tail { - $$ = new_node("cdecl"); - if ($6.qualifier) SwigType_push($3.type,$6.qualifier); - Setattr($$,"type",$5); - Setattr($$,"storage",$1); - Setattr($$,"name",$3.id); - Setattr($$,"decl",$3.type); - Setattr($$,"parms",$3.parms); - Setattr($$,"value",$6.val); - Setattr($$,"throws",$6.throws); - Setattr($$,"throw",$6.throwf); - Setattr($$,"noexcept",$6.nexcept); - if (!$7) { - if (Len(scanner_ccode)) { - String *code = Copy(scanner_ccode); - Setattr($$,"code",code); - Delete(code); - } - } else { - Node *n = $7; - while (n) { - String *type = Copy($5); - Setattr(n,"type",type); - Setattr(n,"storage",$1); - n = nextSibling(n); - Delete(type); - } - } - if ($6.bitfield) { - Setattr($$,"bitfield", $6.bitfield); + set_nextSibling($$, $9); } - if (Strstr($3.id,"::")) { - String *p = Swig_scopename_prefix($3.id); - if (p) { - if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) || - (Classprefix && Strcmp(p, Classprefix) == 0)) { - String *lstr = Swig_scopename_last($3.id); - Setattr($$,"name",lstr); - Delete(lstr); - set_nextSibling($$,$7); - } else { - Delete($$); - $$ = $7; - } - Delete(p); - } else { - Delete($$); - $$ = $7; - } - } else { - set_nextSibling($$,$7); - } + if ($4.qualifier && $1 && Strstr($1, "static")) + Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$)); } ; @@ -3057,27 +3323,29 @@ c_decl_tail : SEMI { $$ = 0; Clear(scanner_ccode); } - | COMMA declarator initializer c_decl_tail { + | COMMA declarator cpp_const initializer c_decl_tail { $$ = new_node("cdecl"); if ($3.qualifier) SwigType_push($2.type,$3.qualifier); + Setattr($$,"refqualifier",$3.refqualifier); Setattr($$,"name",$2.id); Setattr($$,"decl",$2.type); Setattr($$,"parms",$2.parms); - Setattr($$,"value",$3.val); + Setattr($$,"value",$4.val); Setattr($$,"throws",$3.throws); Setattr($$,"throw",$3.throwf); Setattr($$,"noexcept",$3.nexcept); - if ($3.bitfield) { - Setattr($$,"bitfield", $3.bitfield); + Setattr($$,"final",$3.final); + if ($4.bitfield) { + Setattr($$,"bitfield", $4.bitfield); } - if (!$4) { + if (!$5) { if (Len(scanner_ccode)) { String *code = Copy(scanner_ccode); Setattr($$,"code",code); Delete(code); } } else { - set_nextSibling($$,$4); + set_nextSibling($$, $5); } } | LBRACE { @@ -3095,33 +3363,8 @@ c_decl_tail : SEMI { } ; -initializer : def_args { - $$ = $1; - $$.qualifier = 0; - $$.throws = 0; - $$.throwf = 0; - $$.nexcept = 0; - } - | type_qualifier def_args { - $$ = $2; - $$.qualifier = $1; - $$.throws = 0; - $$.throwf = 0; - $$.nexcept = 0; - } - | exception_specification def_args { - $$ = $2; - $$.qualifier = 0; - $$.throws = $1.throws; - $$.throwf = $1.throwf; - $$.nexcept = $1.nexcept; - } - | type_qualifier exception_specification def_args { - $$ = $3; - $$.qualifier = $1; - $$.throws = $2.throws; - $$.throwf = $2.throwf; - $$.nexcept = $2.nexcept; +initializer : def_args { + $$ = $1; } ; @@ -3264,7 +3507,7 @@ c_enum_decl : storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBR Namespaceprefix = Swig_symbol_qualifiedscopename(0); } } - | storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBRACE declarator initializer c_decl_tail { + | storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBRACE declarator cpp_const initializer c_decl_tail { Node *n; SwigType *ty = 0; String *unnamed = 0; @@ -3311,8 +3554,8 @@ c_enum_decl : storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBR SetFlag(n,"unnamedinstance"); Delete(cty); } - if ($10) { - Node *p = $10; + if ($11) { + Node *p = $11; set_nextSibling(n,p); while (p) { SwigType *cty = Copy(ty); @@ -3400,6 +3643,7 @@ c_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end { Setattr($$,"throws",$6.throws); Setattr($$,"throw",$6.throwf); Setattr($$,"noexcept",$6.nexcept); + Setattr($$,"final",$6.final); err = 0; } } @@ -3443,7 +3687,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { Setattr($$,"prev_symtab",Swig_symbol_current()); /* If the class name is qualified. We need to create or lookup namespace/scope entries */ - scope = resolve_create_node_scope($3); + scope = resolve_create_node_scope($3, 1); /* save nscope_inner to the class - it may be overwritten in nested classes*/ Setattr($$, "nested:innerscope", nscope_inner); Setattr($$, "nested:nscope", nscope); @@ -3635,7 +3879,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { if ($9) { appendSibling($$, $9); } - } else if (!SwigType_istemplate(ty) && template_parameters == 0) { /* for tempalte we need the class itself */ + } else if (!SwigType_istemplate(ty) && template_parameters == 0) { /* for template we need the class itself */ $$ = $9; } } else { @@ -3646,6 +3890,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { while (Getattr(outer, "nested:outer")) outer = Getattr(outer, "nested:outer"); appendSibling(outer, $$); + Swig_symbol_setscope(cscope); /* declaration goes in the parent scope */ add_symbols($9); set_scope_to_global(); Delete(Namespaceprefix); @@ -3820,12 +4065,12 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { ; cpp_opt_declarators : SEMI { $$ = 0; } - | declarator initializer c_decl_tail { + | declarator cpp_const initializer c_decl_tail { $$ = new_node("cdecl"); Setattr($$,"name",$1.id); Setattr($$,"decl",$1.type); Setattr($$,"parms",$1.parms); - set_nextSibling($$,$3); + set_nextSibling($$, $4); } ; /* ------------------------------------------------------------ @@ -3851,10 +4096,11 @@ cpp_forward_class_decl : storage_class cpptype idcolon SEMI { ------------------------------------------------------------ */ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { - if (currentOuterClass) - Setattr(currentOuterClass, "template_parameters", template_parameters); + if (currentOuterClass) + Setattr(currentOuterClass, "template_parameters", template_parameters); template_parameters = $3; - } cpp_temp_possible { + parsing_template_declaration = 1; + } cpp_template_possible { String *tname = 0; int error = 0; @@ -4106,6 +4352,7 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_parameters = Getattr(currentOuterClass, "template_parameters"); else template_parameters = 0; + parsing_template_declaration = 0; } /* Explicit template instantiation */ @@ -4121,7 +4368,7 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { } ; -cpp_temp_possible: c_decl { +cpp_template_possible: c_decl { $$ = $1; } | cpp_class_decl { @@ -4130,9 +4377,6 @@ cpp_temp_possible: c_decl { | cpp_constructor_decl { $$ = $1; } - | cpp_static_assert { - $$ = $1; - } | cpp_template_decl { $$ = 0; } @@ -4247,32 +4491,61 @@ cpp_using_decl : USING idcolon SEMI { cpp_namespace_decl : NAMESPACE idcolon LBRACE { Hash *h; - $1 = Swig_symbol_current(); - h = Swig_symbol_clookup($2,0); - if (h && ($1 == Getattr(h,"sym:symtab")) && (Strcmp(nodeType(h),"namespace") == 0)) { - if (Getattr(h,"alias")) { - h = Getattr(h,"namespace"); - Swig_warning(WARN_PARSE_NAMESPACE_ALIAS, cparse_file, cparse_line, "Namespace alias '%s' not allowed here. Assuming '%s'\n", - $2, Getattr(h,"name")); - $2 = Getattr(h,"name"); + Node *parent_ns = 0; + List *scopes = Swig_scopename_tolist($2); + int ilen = Len(scopes); + int i; + +/* +Printf(stdout, "==== Namespace %s creation...\n", $2); +*/ + $$ = 0; + for (i = 0; i < ilen; i++) { + Node *ns = new_node("namespace"); + Symtab *current_symtab = Swig_symbol_current(); + String *scopename = Getitem(scopes, i); + Setattr(ns, "name", scopename); + $$ = ns; + if (parent_ns) + appendChild(parent_ns, ns); + parent_ns = ns; + h = Swig_symbol_clookup(scopename, 0); + if (h && (current_symtab == Getattr(h, "sym:symtab")) && (Strcmp(nodeType(h), "namespace") == 0)) { +/* +Printf(stdout, " Scope %s [found C++17 style]\n", scopename); +*/ + if (Getattr(h, "alias")) { + h = Getattr(h, "namespace"); + Swig_warning(WARN_PARSE_NAMESPACE_ALIAS, cparse_file, cparse_line, "Namespace alias '%s' not allowed here. Assuming '%s'\n", + scopename, Getattr(h, "name")); + scopename = Getattr(h, "name"); + } + Swig_symbol_setscope(Getattr(h, "symtab")); + } else { +/* +Printf(stdout, " Scope %s [creating single scope C++17 style]\n", scopename); +*/ + h = Swig_symbol_newscope(); + Swig_symbol_setscopename(scopename); } - Swig_symbol_setscope(Getattr(h,"symtab")); - } else { - Swig_symbol_newscope(); - Swig_symbol_setscopename($2); + Delete(Namespaceprefix); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); } - Delete(Namespaceprefix); - Namespaceprefix = Swig_symbol_qualifiedscopename(0); + Delete(scopes); } interface RBRACE { - Node *n = $5; - set_nodeType(n,"namespace"); - Setattr(n,"name",$2); - Setattr(n,"symtab", Swig_symbol_popscope()); - Swig_symbol_setscope($1); - $$ = n; - Delete(Namespaceprefix); - Namespaceprefix = Swig_symbol_qualifiedscopename(0); - add_symbols($$); + Node *n = $4; + Node *top_ns = 0; + do { + Setattr(n, "symtab", Swig_symbol_popscope()); + Delete(Namespaceprefix); + Namespaceprefix = Swig_symbol_qualifiedscopename(0); + add_symbols(n); + top_ns = n; + n = parentNode(n); + } while(n); + appendChild($4, firstChild($5)); + Delete($5); + $$ = top_ns; } | NAMESPACE LBRACE { Hash *h; @@ -4371,7 +4644,7 @@ cpp_members : cpp_member cpp_members { /* A class member. May be data or a function. Static or virtual as well */ -cpp_member : c_declaration { $$ = $1; } +cpp_member_no_dox : c_declaration { $$ = $1; } | cpp_constructor_decl { $$ = $1; if (extendmode && current_class) { @@ -4390,7 +4663,6 @@ cpp_member : c_declaration { $$ = $1; } default_arguments($$); } | cpp_destructor_decl { $$ = $1; } - | cpp_static_assert { $$ = $1; } | cpp_protection_decl { $$ = $1; } | cpp_swig_directive { $$ = $1; } | cpp_conversion_operator { $$ = $1; } @@ -4406,6 +4678,18 @@ cpp_member : c_declaration { $$ = $1; } | fragment_directive {$$ = $1; } | types_directive {$$ = $1; } | SEMI { $$ = 0; } + +cpp_member : cpp_member_no_dox { + $$ = $1; + } + | DOXYGENSTRING cpp_member_no_dox { + $$ = $2; + set_comment($2, $1); + } + | cpp_member_no_dox DOXYGENPOSTSTRING { + $$ = $1; + set_comment($1, $2); + } ; /* Possibly a constructor */ @@ -4426,6 +4710,7 @@ cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end { Setattr($$,"throws",$6.throws); Setattr($$,"throw",$6.throwf); Setattr($$,"noexcept",$6.nexcept); + Setattr($$,"final",$6.final); if (Len(scanner_ccode)) { String *code = Copy(scanner_ccode); Setattr($$,"code",code); @@ -4462,8 +4747,11 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end { Setattr($$,"throws",$6.throws); Setattr($$,"throw",$6.throwf); Setattr($$,"noexcept",$6.nexcept); + Setattr($$,"final",$6.final); if ($6.val) Setattr($$,"value",$6.val); + if ($6.qualifier) + Swig_error(cparse_file, cparse_line, "Destructor %s %s cannot have a qualifier.\n", Swig_name_decl($$), SwigType_str($6.qualifier, 0)); add_symbols($$); } @@ -4480,6 +4768,7 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end { Setattr($$,"throws",$7.throws); Setattr($$,"throw",$7.throwf); Setattr($$,"noexcept",$7.nexcept); + Setattr($$,"final",$7.final); if ($7.val) Setattr($$,"value",$7.val); if (Len(scanner_ccode)) { @@ -4493,7 +4782,8 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end { Setattr($$,"decl",decl); Delete(decl); } - + if ($7.qualifier) + Swig_error(cparse_file, cparse_line, "Destructor %s %s cannot have a qualifier.\n", Swig_name_decl($$), SwigType_str($7.qualifier, 0)); add_symbols($$); } ; @@ -4510,6 +4800,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p if ($8.qualifier) { SwigType_push($4,$8.qualifier); } + Setattr($$,"refqualifier",$8.refqualifier); Setattr($$,"decl",$4); Setattr($$,"parms",$6); Setattr($$,"conversion_operator","1"); @@ -4527,6 +4818,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p if ($8.qualifier) { SwigType_push(decl,$8.qualifier); } + Setattr($$,"refqualifier",$8.refqualifier); Setattr($$,"decl",decl); Setattr($$,"parms",$6); Setattr($$,"conversion_operator","1"); @@ -4544,6 +4836,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p if ($8.qualifier) { SwigType_push(decl,$8.qualifier); } + Setattr($$,"refqualifier",$8.refqualifier); Setattr($$,"decl",decl); Setattr($$,"parms",$6); Setattr($$,"conversion_operator","1"); @@ -4563,6 +4856,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p if ($9.qualifier) { SwigType_push(decl,$9.qualifier); } + Setattr($$,"refqualifier",$9.refqualifier); Setattr($$,"decl",decl); Setattr($$,"parms",$7); Setattr($$,"conversion_operator","1"); @@ -4579,6 +4873,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p if ($7.qualifier) { SwigType_push(t,$7.qualifier); } + Setattr($$,"refqualifier",$7.refqualifier); Setattr($$,"decl",t); Setattr($$,"parms",$5); Setattr($$,"conversion_operator","1"); @@ -4594,7 +4889,8 @@ cpp_catch_decl : CATCH LPAREN parms RPAREN LBRACE { } ; -/* static_assert(bool, const char*); */ +/* static_assert(bool, const char*); (C++11) + * static_assert(bool); (C++17) */ cpp_static_assert : STATIC_ASSERT LPAREN { skip_balanced('(',')'); $$ = 0; @@ -4648,23 +4944,35 @@ cpp_swig_directive: pragma_directive { $$ = $1; } cpp_end : cpp_const SEMI { Clear(scanner_ccode); $$.val = 0; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; + $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; } | cpp_const EQUAL default_delete SEMI { Clear(scanner_ccode); $$.val = $3.val; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; + $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; } | cpp_const LBRACE { skip_balanced('{','}'); $$.val = 0; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; + $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; } ; @@ -4672,28 +4980,34 @@ cpp_vend : cpp_const SEMI { Clear(scanner_ccode); $$.val = 0; $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; } | cpp_const EQUAL definetype SEMI { Clear(scanner_ccode); $$.val = $3.val; $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; - $$.nexcept = $1.nexcept; + $$.nexcept = $1.nexcept; + $$.final = $1.final; } | cpp_const LBRACE { skip_balanced('{','}'); $$.val = 0; $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; - $$.nexcept = $1.nexcept; + $$.nexcept = $1.nexcept; + $$.final = $1.final; } ; @@ -4772,20 +5086,31 @@ rawparms : parm ptail { set_nextSibling($1,$2); $$ = $1; } - | empty { $$ = 0; } + | empty { + $$ = 0; + previousNode = currentNode; + currentNode=0; + } ; ptail : COMMA parm ptail { set_nextSibling($2,$3); $$ = $2; } + | COMMA DOXYGENPOSTSTRING parm ptail { + set_comment(previousNode, $2); + set_nextSibling($3, $4); + $$ = $3; + } | empty { $$ = 0; } ; -parm : rawtype parameter_declarator { +parm_no_dox : rawtype parameter_declarator { SwigType_push($1,$2.type); $$ = NewParmWithoutFileLineInfo($1,$2.id); + previousNode = currentNode; + currentNode = $$; Setfile($$,cparse_file); Setline($$,cparse_line); if ($2.defarg) { @@ -4795,6 +5120,8 @@ parm : rawtype parameter_declarator { | TEMPLATE LESSTHAN cpptype GREATERTHAN cpptype idcolon def_args { $$ = NewParmWithoutFileLineInfo(NewStringf("template %s %s", $5,$6), 0); + previousNode = currentNode; + currentNode = $$; Setfile($$,cparse_file); Setline($$,cparse_line); if ($7.val) { @@ -4804,11 +5131,26 @@ parm : rawtype parameter_declarator { | PERIOD PERIOD PERIOD { SwigType *t = NewString("v(...)"); $$ = NewParmWithoutFileLineInfo(t, 0); + previousNode = currentNode; + currentNode = $$; Setfile($$,cparse_file); Setline($$,cparse_line); } ; +parm : parm_no_dox { + $$ = $1; + } + | DOXYGENSTRING parm_no_dox { + $$ = $2; + set_comment($2, $1); + } + | parm_no_dox DOXYGENPOSTSTRING { + $$ = $1; + set_comment($1, $2); + } + ; + valparms : rawvalparms { Parm *p; $$ = $1; @@ -4883,6 +5225,7 @@ def_args : EQUAL definetype { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } } | EQUAL definetype LBRACKET expr RBRACKET { @@ -4896,6 +5239,7 @@ def_args : EQUAL definetype { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } else { $$.val = NewStringf("%s[%s]",$2.val,$4.val); } @@ -4909,6 +5253,7 @@ def_args : EQUAL definetype { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | COLON expr { $$.val = 0; @@ -4918,6 +5263,7 @@ def_args : EQUAL definetype { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | empty { $$.val = 0; @@ -4927,6 +5273,7 @@ def_args : EQUAL definetype { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } ; @@ -4943,6 +5290,28 @@ parameter_declarator : declarator def_args { $$.id = 0; $$.defarg = $1.rawval ? $1.rawval : $1.val; } + /* Member function pointers with qualifiers. eg. + int f(short (Funcs::*parm)(bool) const); */ + | direct_declarator LPAREN parms RPAREN cv_ref_qualifier { + SwigType *t; + $$ = $1; + t = NewStringEmpty(); + SwigType_add_function(t,$3); + if ($5.qualifier) + SwigType_push(t, $5.qualifier); + if (!$$.have_parms) { + $$.parms = $3; + $$.have_parms = 1; + } + if (!$$.type) { + $$.type = t; + } else { + SwigType_push(t, $$.type); + Delete($$.type); + $$.type = t; + } + $$.defarg = 0; + } ; plain_declarator : declarator { @@ -4979,6 +5348,27 @@ plain_declarator : declarator { $$.parms = 0; } } + /* Member function pointers with qualifiers. eg. + int f(short (Funcs::*parm)(bool) const) */ + | direct_declarator LPAREN parms RPAREN cv_ref_qualifier { + SwigType *t; + $$ = $1; + t = NewStringEmpty(); + SwigType_add_function(t, $3); + if ($5.qualifier) + SwigType_push(t, $5.qualifier); + if (!$$.have_parms) { + $$.parms = $3; + $$.have_parms = 1; + } + if (!$$.type) { + $$.type = t; + } else { + SwigType_push(t, $$.type); + Delete($$.type); + $$.type = t; + } + } | empty { $$.type = 0; $$.id = 0; @@ -4986,7 +5376,6 @@ plain_declarator : declarator { } ; - declarator : pointer notso_direct_declarator { $$ = $2; if ($$.type) { @@ -5339,7 +5728,7 @@ direct_declarator : idcolon { } SwigType_add_rvalue_reference($$.type); } - | LPAREN idcolon DSTAR direct_declarator RPAREN { + | LPAREN idcolon DSTAR declarator RPAREN { SwigType *t; $$ = $4; t = NewStringEmpty(); @@ -5349,7 +5738,42 @@ direct_declarator : idcolon { Delete($$.type); } $$.type = t; + } + | LPAREN idcolon DSTAR type_qualifier declarator RPAREN { + SwigType *t; + $$ = $5; + t = NewStringEmpty(); + SwigType_add_memberpointer(t, $2); + SwigType_push(t, $4); + if ($$.type) { + SwigType_push(t, $$.type); + Delete($$.type); } + $$.type = t; + } + | LPAREN idcolon DSTAR abstract_declarator RPAREN { + SwigType *t; + $$ = $4; + t = NewStringEmpty(); + SwigType_add_memberpointer(t, $2); + if ($$.type) { + SwigType_push(t, $$.type); + Delete($$.type); + } + $$.type = t; + } + | LPAREN idcolon DSTAR type_qualifier abstract_declarator RPAREN { + SwigType *t; + $$ = $5; + t = NewStringEmpty(); + SwigType_add_memberpointer(t, $2); + SwigType_push(t, $4); + if ($$.type) { + SwigType_push(t, $$.type); + Delete($$.type); + } + $$.type = t; + } | direct_declarator LBRACKET RBRACKET { SwigType *t; $$ = $1; @@ -5388,7 +5812,7 @@ direct_declarator : idcolon { Delete($$.type); $$.type = t; } - } + } /* User-defined string literals. eg. int operator"" _mySuffix(const char* val, int length) {...} */ /* This produces one S/R conflict. */ @@ -5499,6 +5923,14 @@ abstract_declarator : pointer { $$.parms = 0; $$.have_parms = 0; } + | idcolon DSTAR type_qualifier { + $$.type = NewStringEmpty(); + SwigType_add_memberpointer($$.type, $1); + SwigType_push($$.type, $3); + $$.id = 0; + $$.parms = 0; + $$.have_parms = 0; + } | pointer idcolon DSTAR { SwigType *t = NewStringEmpty(); $$.type = $1; @@ -5576,6 +6008,24 @@ direct_abstract_declarator : direct_abstract_declarator LBRACKET RBRACKET { $$.have_parms = 1; } } + | direct_abstract_declarator LPAREN parms RPAREN cv_ref_qualifier { + SwigType *t; + $$ = $1; + t = NewStringEmpty(); + SwigType_add_function(t,$3); + SwigType_push(t, $5.qualifier); + if (!$$.type) { + $$.type = t; + } else { + SwigType_push(t,$$.type); + Delete($$.type); + $$.type = t; + } + if (!$$.have_parms) { + $$.parms = $3; + $$.have_parms = 1; + } + } | LPAREN parms RPAREN { $$.type = NewStringEmpty(); SwigType_add_function($$.type,$2); @@ -5610,6 +6060,33 @@ pointer : STAR type_qualifier pointer { } ; +/* cv-qualifier plus C++11 ref-qualifier for non-static member functions */ +cv_ref_qualifier : type_qualifier { + $$.qualifier = $1; + $$.refqualifier = 0; + } + | type_qualifier ref_qualifier { + $$.qualifier = $1; + $$.refqualifier = $2; + SwigType_push($$.qualifier, $2); + } + | ref_qualifier { + $$.qualifier = NewStringEmpty(); + $$.refqualifier = $1; + SwigType_push($$.qualifier, $1); + } + ; + +ref_qualifier : AND { + $$ = NewStringEmpty(); + SwigType_add_reference($$); + } + | LAND { + $$ = NewStringEmpty(); + SwigType_add_rvalue_reference($$); + } + ; + type_qualifier : type_qualifier_raw { $$ = NewStringEmpty(); if ($1) SwigType_add_qualifier($$,$1); @@ -5828,13 +6305,15 @@ definetype : { /* scanner_check_typedef(); */ } expr { if ($$.type == T_STRING) { $$.rawval = NewStringf("\"%(escape)s\"",$$.val); } else if ($$.type != T_CHAR && $$.type != T_WSTRING && $$.type != T_WCHAR) { - $$.rawval = 0; + $$.rawval = NewStringf("%s", $$.val); } $$.qualifier = 0; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; scanner_ignore_typedef(); } | default_delete { @@ -5856,10 +6335,12 @@ deleted_definition : DELETE_KW { $$.rawval = 0; $$.type = T_STRING; $$.qualifier = 0; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } ; @@ -5869,10 +6350,12 @@ explicit_default : DEFAULT { $$.rawval = 0; $$.type = T_STRING; $$.qualifier = 0; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } ; @@ -5882,28 +6365,70 @@ ename : identifier { $$ = $1; } | empty { $$ = (char *) 0;} ; -optional_constant_directive : constant_directive { $$ = $1; } - | empty { $$ = 0; } - ; +constant_directives : constant_directive + | constant_directive constant_directives + ; + +optional_ignored_defines + : constant_directives + | empty + ; /* Enum lists - any #define macros (constant directives) within the enum list are ignored. Trailing commas accepted. */ -enumlist : enumlist COMMA optional_constant_directive edecl optional_constant_directive { - Node *leftSibling = Getattr($1,"_last"); - set_nextSibling(leftSibling,$4); - Setattr($1,"_last",$4); - $$ = $1; - } - | enumlist COMMA optional_constant_directive { - $$ = $1; - } - | optional_constant_directive edecl optional_constant_directive { - Setattr($2,"_last",$2); - $$ = $2; - } - | optional_constant_directive { - $$ = 0; - } - ; + +/* + Note that "_last" attribute is not supposed to be set on the last enum element, as might be expected from its name, but on the _first_ one, and _only_ on it, + so we propagate it back to the first item while parsing and reset it on all the subsequent ones. + */ + +enumlist : enumlist_item { + Setattr($1,"_last",$1); + $$ = $1; + } + | enumlist_item DOXYGENPOSTSTRING { + Setattr($1,"_last",$1); + set_comment($1, $2); + $$ = $1; + } + | enumlist_item COMMA enumlist { + if ($3) { + set_nextSibling($1, $3); + Setattr($1,"_last",Getattr($3,"_last")); + Setattr($3,"_last",NULL); + } else { + Setattr($1,"_last",$1); + } + $$ = $1; + } + | enumlist_item COMMA DOXYGENPOSTSTRING enumlist { + if ($4) { + set_nextSibling($1, $4); + Setattr($1,"_last",Getattr($4,"_last")); + Setattr($4,"_last",NULL); + } else { + Setattr($1,"_last",$1); + } + set_comment($1, $3); + $$ = $1; + } + | optional_ignored_defines { + $$ = 0; + } + ; + +enumlist_item : optional_ignored_defines edecl_with_dox optional_ignored_defines { + $$ = $2; + } + ; + +edecl_with_dox : edecl { + $$ = $1; + } + | DOXYGENSTRING edecl { + $$ = $2; + set_comment($2, $1); + } + ; edecl : identifier { SwigType *type = NewSwigType(T_INT); @@ -5960,7 +6485,33 @@ expr : valexpr { $$ = $1; } } ; -valexpr : exprnum { $$ = $1; } +/* simple member access expressions */ +exprmem : ID ARROW ID { + $$.val = NewStringf("%s->%s", $1, $3); + $$.type = 0; + } + | exprmem ARROW ID { + $$ = $1; + Printf($$.val, "->%s", $3); + } +/* This generates a shift-reduce + | ID PERIOD ID { + $$.val = NewStringf("%s.%s", $1, $3); + $$.type = 0; + } +*/ + | exprmem PERIOD ID { + $$ = $1; + Printf($$.val, ".%s", $3); + } + ; + +valexpr : exprnum { + $$ = $1; + } + | exprmem { + $$ = $1; + } | string { $$.val = $1; $$.type = T_STRING; @@ -5993,6 +6544,7 @@ valexpr : exprnum { $$ = $1; } $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | WCHARCONST { $$.val = NewString($1); @@ -6006,13 +6558,17 @@ valexpr : exprnum { $$ = $1; } $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } /* grouping */ | LPAREN expr RPAREN %prec CAST { - $$.val = NewStringf("(%s)",$2.val); + $$.val = NewStringf("(%s)",$2.val); + if ($2.rawval) { + $$.rawval = NewStringf("(%s)",$2.rawval); + } $$.type = $2.type; - } + } /* A few common casting operations */ @@ -6032,6 +6588,7 @@ valexpr : exprnum { $$ = $1; } break; } } + $$.type = promote($2.type, $4.type); } | LPAREN expr pointer RPAREN expr %prec CAST { $$ = $5; @@ -6095,81 +6652,81 @@ exprnum : NUM_INT { $$ = $1; } ; exprcompound : expr PLUS expr { - $$.val = NewStringf("%s+%s",$1.val,$3.val); + $$.val = NewStringf("%s+%s", COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote($1.type,$3.type); } | expr MINUS expr { - $$.val = NewStringf("%s-%s",$1.val,$3.val); + $$.val = NewStringf("%s-%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote($1.type,$3.type); } | expr STAR expr { - $$.val = NewStringf("%s*%s",$1.val,$3.val); + $$.val = NewStringf("%s*%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote($1.type,$3.type); } | expr SLASH expr { - $$.val = NewStringf("%s/%s",$1.val,$3.val); + $$.val = NewStringf("%s/%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote($1.type,$3.type); } | expr MODULO expr { - $$.val = NewStringf("%s%%%s",$1.val,$3.val); + $$.val = NewStringf("%s%%%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote($1.type,$3.type); } | expr AND expr { - $$.val = NewStringf("%s&%s",$1.val,$3.val); + $$.val = NewStringf("%s&%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote($1.type,$3.type); } | expr OR expr { - $$.val = NewStringf("%s|%s",$1.val,$3.val); + $$.val = NewStringf("%s|%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote($1.type,$3.type); } | expr XOR expr { - $$.val = NewStringf("%s^%s",$1.val,$3.val); + $$.val = NewStringf("%s^%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote($1.type,$3.type); } | expr LSHIFT expr { - $$.val = NewStringf("%s << %s",$1.val,$3.val); + $$.val = NewStringf("%s << %s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote_type($1.type); } | expr RSHIFT expr { - $$.val = NewStringf("%s >> %s",$1.val,$3.val); + $$.val = NewStringf("%s >> %s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote_type($1.type); } | expr LAND expr { - $$.val = NewStringf("%s&&%s",$1.val,$3.val); + $$.val = NewStringf("%s&&%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr LOR expr { - $$.val = NewStringf("%s||%s",$1.val,$3.val); + $$.val = NewStringf("%s||%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr EQUALTO expr { - $$.val = NewStringf("%s==%s",$1.val,$3.val); + $$.val = NewStringf("%s==%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr NOTEQUALTO expr { - $$.val = NewStringf("%s!=%s",$1.val,$3.val); + $$.val = NewStringf("%s!=%s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = cparse_cplusplus ? T_BOOL : T_INT; } /* Sadly this causes 2 reduce-reduce conflicts with templates. FIXME resolve these. | expr GREATERTHAN expr { - $$.val = NewStringf("%s > %s", $1.val, $3.val); + $$.val = NewStringf("%s > %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3)); $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr LESSTHAN expr { - $$.val = NewStringf("%s < %s", $1.val, $3.val); + $$.val = NewStringf("%s < %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3)); $$.type = cparse_cplusplus ? T_BOOL : T_INT; } */ | expr GREATERTHANOREQUALTO expr { - $$.val = NewStringf("%s >= %s", $1.val, $3.val); + $$.val = NewStringf("%s >= %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3)); $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr LESSTHANOREQUALTO expr { - $$.val = NewStringf("%s <= %s", $1.val, $3.val); + $$.val = NewStringf("%s <= %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3)); $$.type = cparse_cplusplus ? T_BOOL : T_INT; } | expr QUESTIONMARK expr COLON expr %prec QUESTIONMARK { - $$.val = NewStringf("%s?%s:%s", $1.val, $3.val, $5.val); + $$.val = NewStringf("%s?%s:%s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3), COMPOUND_EXPR_VAL($5)); /* This may not be exactly right, but is probably good enough * for the purposes of parsing constant expressions. */ $$.type = promote($3.type, $5.type); @@ -6187,7 +6744,7 @@ exprcompound : expr PLUS expr { $$.type = $2.type; } | LNOT expr { - $$.val = NewStringf("!%s",$2.val); + $$.val = NewStringf("!%s",COMPOUND_EXPR_VAL($2)); $$.type = T_INT; } | type LPAREN { @@ -6295,7 +6852,6 @@ access_specifier : PUBLIC { $$ = (char*)"public"; } | PROTECTED { $$ = (char*)"protected"; } ; - templcpptype : CLASS { $$ = (char*)"class"; if (!inherit_list) last_cpptype = $$; @@ -6327,6 +6883,28 @@ cpptype : templcpptype { } ; +classkey : CLASS { + $$ = (char*)"class"; + if (!inherit_list) last_cpptype = $$; + } + | STRUCT { + $$ = (char*)"struct"; + if (!inherit_list) last_cpptype = $$; + } + | UNION { + $$ = (char*)"union"; + if (!inherit_list) last_cpptype = $$; + } + ; + +classkeyopt : classkey { + $$ = $1; + } + | empty { + $$ = 0; + } + ; + opt_virtual : VIRTUAL | empty ; @@ -6335,62 +6913,92 @@ virt_specifier_seq : OVERRIDE { $$ = 0; } | FINAL { - $$ = 0; + $$ = NewString("1"); } | FINAL OVERRIDE { - $$ = 0; + $$ = NewString("1"); } | OVERRIDE FINAL { - $$ = 0; + $$ = NewString("1"); } ; +virt_specifier_seq_opt : virt_specifier_seq { + $$ = $1; + } + | empty { + $$ = 0; + } + ; + exception_specification : THROW LPAREN parms RPAREN { $$.throws = $3; $$.throwf = NewString("1"); $$.nexcept = 0; + $$.final = 0; } | NOEXCEPT { $$.throws = 0; $$.throwf = 0; $$.nexcept = NewString("true"); + $$.final = 0; } | virt_specifier_seq { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = $1; + } + | THROW LPAREN parms RPAREN virt_specifier_seq { + $$.throws = $3; + $$.throwf = NewString("1"); + $$.nexcept = 0; + $$.final = $5; } | NOEXCEPT virt_specifier_seq { $$.throws = 0; $$.throwf = 0; $$.nexcept = NewString("true"); + $$.final = $2; } | NOEXCEPT LPAREN expr RPAREN { $$.throws = 0; $$.throwf = 0; $$.nexcept = $3.val; + $$.final = 0; } ; -cpp_const : type_qualifier { +qualifiers_exception_specification : cv_ref_qualifier { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; - $$.qualifier = $1; + $$.final = 0; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; } | exception_specification { $$ = $1; $$.qualifier = 0; + $$.refqualifier = 0; } - | type_qualifier exception_specification { + | cv_ref_qualifier exception_specification { $$ = $2; - $$.qualifier = $1; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; + } + ; + +cpp_const : qualifiers_exception_specification { + $$ = $1; } | empty { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; - $$.qualifier = 0; + $$.final = 0; + $$.qualifier = 0; + $$.refqualifier = 0; } ; @@ -6401,6 +7009,9 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; + if ($1.qualifier) + Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n"); } | cpp_const ctor_initializer LBRACE { skip_balanced('{','}'); @@ -6409,6 +7020,9 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; + if ($1.qualifier) + Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n"); } | LPAREN parms RPAREN SEMI { Clear(scanner_ccode); @@ -6418,6 +7032,7 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | LPAREN parms RPAREN LBRACE { skip_balanced('{','}'); @@ -6427,6 +7042,7 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | EQUAL definetype SEMI { $$.have_parms = 0; @@ -6434,6 +7050,7 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; + $$.final = 0; } | exception_specification EQUAL default_delete SEMI { $$.have_parms = 0; @@ -6441,6 +7058,9 @@ ctor_end : cpp_const ctor_initializer SEMI { $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; + $$.final = $1.final; + if ($1.qualifier) + Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n"); } ; diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index e575073a4..6b1a27014 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -30,8 +30,10 @@ static void add_parms(ParmList *p, List *patchlist, List *typelist) { while (p) { SwigType *ty = Getattr(p, "type"); SwigType *val = Getattr(p, "value"); + SwigType *name = Getattr(p, "name"); Append(typelist, ty); Append(typelist, val); + Append(typelist, name); Append(patchlist, val); p = nextSibling(p); } @@ -49,32 +51,31 @@ void Swig_cparse_debug_templates(int x) { * template parameters * ----------------------------------------------------------------------------- */ -static int cparse_template_expand(Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist) { +static void cparse_template_expand(Node *templnode, Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist) { static int expanded = 0; - int ret; String *nodeType; if (!n) - return 0; + return; nodeType = nodeType(n); if (Getattr(n, "error")) - return 0; + return; if (Equal(nodeType, "template")) { /* Change the node type back to normal */ if (!expanded) { expanded = 1; set_nodeType(n, Getattr(n, "templatetype")); - ret = cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist); + cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist); expanded = 0; - return ret; + return; } else { /* Called when template appears inside another template */ /* Member templates */ set_nodeType(n, Getattr(n, "templatetype")); - ret = cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist); + cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist); set_nodeType(n, "template"); - return ret; + return; } } else if (Equal(nodeType, "cdecl")) { /* A simple C declaration */ @@ -131,7 +132,7 @@ static int cparse_template_expand(Node *n, String *tname, String *rname, String { Node *cn = firstChild(n); while (cn) { - cparse_template_expand(cn, tname, rname, templateargs, patchlist, typelist, cpatchlist); + cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist); cn = nextSibling(cn); } } @@ -177,25 +178,30 @@ static int cparse_template_expand(Node *n, String *tname, String *rname, String add_parms(Getattr(n, "parms"), cpatchlist, typelist); add_parms(Getattr(n, "throws"), cpatchlist, typelist); } else if (Equal(nodeType, "destructor")) { - String *name = Getattr(n, "name"); - if (name) { - if (strchr(Char(name), '<')) - Append(patchlist, Getattr(n, "name")); - else - Append(name, templateargs); - } - name = Getattr(n, "sym:name"); - if (name) { - if (strchr(Char(name), '<')) { - String *sn = Copy(tname); - Setattr(n, "sym:name", sn); - Delete(sn); - } else { - Replace(name, tname, rname, DOH_REPLACE_ANY); + /* We only need to patch the dtor of the template itself, not the destructors of any nested classes, so check that the parent of this node is the root + * template node, with the special exception for %extend which adds its methods under an intermediate node. */ + Node* parent = parentNode(n); + if (parent == templnode || (parentNode(parent) == templnode && Equal(nodeType(parent), "extend"))) { + String *name = Getattr(n, "name"); + if (name) { + if (strchr(Char(name), '<')) + Append(patchlist, Getattr(n, "name")); + else + Append(name, templateargs); } + name = Getattr(n, "sym:name"); + if (name) { + if (strchr(Char(name), '<')) { + String *sn = Copy(tname); + Setattr(n, "sym:name", sn); + Delete(sn); + } else { + Replace(name, tname, rname, DOH_REPLACE_ANY); + } + } + /* Setattr(n,"sym:name",name); */ + Append(cpatchlist, Getattr(n, "code")); } - /* Setattr(n,"sym:name",name); */ - Append(cpatchlist, Getattr(n, "code")); } else if (Equal(nodeType, "using")) { String *uname = Getattr(n, "uname"); if (uname && strchr(Char(uname), '<')) { @@ -217,11 +223,10 @@ static int cparse_template_expand(Node *n, String *tname, String *rname, String add_parms(Getattr(n, "throws"), cpatchlist, typelist); cn = firstChild(n); while (cn) { - cparse_template_expand(cn, tname, rname, templateargs, patchlist, typelist, cpatchlist); + cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist); cn = nextSibling(cn); } } - return 0; } static @@ -306,7 +311,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab /* Printf(stdout,"targs = '%s'\n", templateargs); Printf(stdout,"rname = '%s'\n", rname); Printf(stdout,"tname = '%s'\n", tname); */ - cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist); + cparse_template_expand(n, n, tname, rname, templateargs, patchlist, typelist, cpatchlist); /* Set the name */ { diff --git a/Source/CParse/util.c b/Source/CParse/util.c index 0e2136a49..714bb2972 100644 --- a/Source/CParse/util.c +++ b/Source/CParse/util.c @@ -112,12 +112,12 @@ void cparse_normalize_void(Node *n) { } /* ----------------------------------------------------------------------------- - * new_node() + * Swig_cparse_new_node() * * Create an empty parse node, setting file and line number information * ----------------------------------------------------------------------------- */ -Node *new_node(const_String_or_char_ptr tag) { +Node *Swig_cparse_new_node(const_String_or_char_ptr tag) { Node *n = NewHash(); set_nodeType(n,tag); Setfile(n,cparse_file); diff --git a/Source/DOH/memory.c b/Source/DOH/memory.c index b916870d7..e0e4c68bd 100644 --- a/Source/DOH/memory.c +++ b/Source/DOH/memory.c @@ -81,8 +81,8 @@ static void InitPools() { * ---------------------------------------------------------------------- */ int DohCheck(const DOH *ptr) { - register Pool *p = Pools; - register char *cptr = (char *) ptr; + Pool *p = Pools; + char *cptr = (char *) ptr; while (p) { if ((cptr >= p->pbeg) && (cptr < p->pend)) { #ifdef DOH_DEBUG_MEMORY_POOLS diff --git a/Source/DOH/string.c b/Source/DOH/string.c index 490198dfa..94d2737fa 100644 --- a/Source/DOH/string.c +++ b/Source/DOH/string.c @@ -141,15 +141,15 @@ static int String_cmp(DOH *so1, DOH *so2) { static int String_equal(DOH *so1, DOH *so2) { String *s1 = (String *) ObjData(so1); String *s2 = (String *) ObjData(so2); - register int len = s1->len; + int len = s1->len; if (len != s2->len) { return 0; } else { - register char *c1 = s1->str; - register char *c2 = s2->str; + char *c1 = s1->str; + char *c2 = s2->str; #if 0 - register int mlen = len >> 2; - register int i = mlen; + int mlen = len >> 2; + int i = mlen; for (; i; --i) { if (*(c1++) != *(c2++)) return 0; @@ -180,11 +180,11 @@ static int String_hash(DOH *so) { if (s->hashkey >= 0) { return s->hashkey; } else { - register char *c = s->str; - register unsigned int len = s->len > 50 ? 50 : s->len; - register unsigned int h = 0; - register unsigned int mlen = len >> 2; - register unsigned int i = mlen; + char *c = s->str; + unsigned int len = s->len > 50 ? 50 : s->len; + unsigned int h = 0; + unsigned int mlen = len >> 2; + unsigned int i = mlen; for (; i; --i) { h = (h << 5) + *(c++); h = (h << 5) + *(c++); @@ -463,9 +463,9 @@ static int String_seek(DOH *so, long offset, int whence) { { #if 0 - register int sp = s->sp; - register char *tc = s->str; - register int len = s->len; + int sp = s->sp; + char *tc = s->str; + int len = s->len; while (sp != nsp) { int prev = sp + inc; if (prev >= 0 && prev <= len && tc[prev] == '\n') @@ -473,8 +473,8 @@ static int String_seek(DOH *so, long offset, int whence) { sp += inc; } #else - register int sp = s->sp; - register char *tc = s->str; + int sp = s->sp; + char *tc = s->str; if (inc > 0) { while (sp != nsp) { if (tc[++sp] == '\n') @@ -508,12 +508,12 @@ static long String_tell(DOH *so) { static int String_putc(DOH *so, int ch) { String *s = (String *) ObjData(so); - register int len = s->len; - register int sp = s->sp; + int len = s->len; + int sp = s->sp; s->hashkey = -1; if (sp >= len) { - register int maxsize = s->maxsize; - register char *tc = s->str; + int maxsize = s->maxsize; + char *tc = s->str; if (len > (maxsize - 2)) { maxsize *= 2; tc = (char *) DohRealloc(tc, maxsize); @@ -679,7 +679,7 @@ static int replace_simple(String *str, char *token, char *rep, int flags, int co int noquote = 0; char *c, *s, *t, *first; char *q, *q2; - register char *base; + char *base; int i; /* Figure out if anything gets replaced */ diff --git a/Source/Doxygen/doxycommands.h b/Source/Doxygen/doxycommands.h new file mode 100644 index 000000000..1f7b5fa5b --- /dev/null +++ b/Source/Doxygen/doxycommands.h @@ -0,0 +1,170 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * doxycommands.h + * + * Part of the Doxygen comment translation module of SWIG. + * ----------------------------------------------------------------------------- */ + +#ifndef DOXYGENCOMMANDS_H +#define DOXYGENCOMMANDS_H + +// doxy commands are not processed inside this block +const char *CMD_HTML_ONLY = "htmlonly"; +// doxy commands are not processed inside this block +const char *CMD_VERBATIM = "verbatim"; +const char *CMD_LATEX_1 = "f$"; +const char *CMD_LATEX_2 = "f{"; +const char *CMD_LATEX_3 = "f["; +const char *CMD_END_HTML_ONLY = "endhtmlonly"; +const char *CMD_END_VERBATIM = "endverbatim"; +const char *CMD_END_LATEX_1 = "f$"; +const char *CMD_END_LATEX_2 = "f}"; +const char *CMD_END_LATEX_3 = "f]"; + +const char *sectionIndicators[] = { + "attention", "author", "authors", "brief", "bug", "cond", "date", + "deprecated", "details", "else", "elseif", "endcond", "endif", + "exception", "if", "ifnot", "invariant", "note", "par", "param", + "tparam", "post", "pre", "remarks", "remark", "result", "return", + "returns", "retval", "sa", "see", "since", "test", "throw", "throws", + "todo", "version", "warning", "xrefitem" +}; + +const int sectionIndicatorsSize = sizeof(sectionIndicators) / sizeof(*sectionIndicators); + +/* All of the doxygen commands divided up by how they are parsed */ +const char *simpleCommands[] = { + // the first line are escaped chars, except \~, which is a language ID command. + "n", "$", "@", "\\", "&", "~", "<", ">", "#", "%", "\"", ".", "::", + "endcond", + "callgraph", "callergraph", "showinitializer", "hideinitializer", "internal", + "nosubgrouping", "public", "publicsection", "private", "privatesection", + "protected", "protectedsection", "tableofcontents" +}; + +const int simpleCommandsSize = sizeof(simpleCommands) / sizeof(*simpleCommands); + +const char *commandWords[] = { + "a", "b", "c", "e", "em", "p", "def", "enum", "package", "relates", + "namespace", "relatesalso", "anchor", "dontinclude", "include", + "includelineno", "copydoc", "copybrief", "copydetails", "verbinclude", + "htmlinclude", "extends", "implements", "memberof", "related", "relatedalso", + "cite" +}; + +const int commandWordsSize = sizeof(commandWords) / sizeof(*commandWords); + +const char *commandLines[] = { + "addindex", "fn", "name", "line", "var", "skipline", "typedef", "skip", + "until", "property" +}; + +const int commandLinesSize = sizeof(commandLines) / sizeof(*commandLines); + +const char *commandParagraph[] = { + "partofdescription", "result", "return", "returns", "remarks", "remark", + "since", "test", "sa", "see", "pre", "post", "details", "invariant", + "deprecated", "date", "note", "warning", "version", "todo", "bug", + "attention", "brief", "author", "authors", "copyright", "short" +}; + +const int commandParagraphSize = sizeof(commandParagraph) / sizeof(*commandParagraph); + +const char *commandEndCommands[] = { + CMD_HTML_ONLY, "latexonly", "manonly", "xmlonly", "link", "rtfonly" +}; + +const int commandEndCommandsSize = sizeof(commandEndCommands) / sizeof(*commandEndCommands); + +const char *commandWordParagraphs[] = { + "param", "tparam", "throw", "throws", "retval", "exception", "example" +}; + +const int commandWordParagraphsSize = sizeof(commandWordParagraphs) / sizeof(*commandWordParagraphs); + +const char *commandWordLines[] = { + "page", "subsection", "subsubsection", "section", "paragraph", "defgroup", + "snippet", "mainpage" +}; + +const int commandWordLinesSize = sizeof(commandWordLines) / sizeof(*commandWordLines); + +const char *commandWordOWordOWords[] = { + "category", "class", "protocol", "interface", "struct", "union" +}; + +const int commandWordOWordOWordsSize = sizeof(commandWordOWordOWords) / sizeof(*commandWordOWordOWords); + +const char *commandOWords[] = { + "dir", "file", "cond" +}; + +const int commandOWordsSize = sizeof(commandOWords) / sizeof(*commandOWords); + +const char *commandErrorThrowings[] = { + "annotatedclassstd::list", "classhierarchy", "define", "functionindex", "header", + "headerfilestd::list", "inherit", "l", "postheader", "endcode", "enddot", "endmsc", "endhtmlonly", + "endlatexonly", "endmanonly", "endlink", "endverbatim", "endxmlonly", "f]", "f}", "endif", "else", + "endrtfonly" +}; + +const int commandErrorThrowingsSize = sizeof(commandErrorThrowings) / sizeof(*commandErrorThrowings); + +const char *commandUniques[] = { + "xrefitem", "arg", "ingroup", "par", "headerfile", "overload", "weakgroup", "ref", "subpage", "dotfile", "image", "addtogroup", "li", + "if", "ifnot", "elseif", "else", "mscfile", "code", CMD_VERBATIM, "f{", "f[", "f$", "dot", "msc" +}; + +const int commandUniquesSize = sizeof(commandUniques) / sizeof(*commandUniques); + +// These HTML commands are transformed when producing output in other formats. +// Other commands are left intact, but '<' and '> are replaced with entities in HTML +// output. So appears as <varName> in HTML output. The same +// behavior must be repeated by SWIG. See Doxygen doc for the list of commands. +// '<' is prepended to distinguish HTML tags from Doxygen commands. +const char *commandHtml[] = { + "= + "&larr", // <-- + "&rarr" // --> +}; + +const int commandHtmlEntitiesSize = sizeof(commandHtmlEntities) / sizeof(*commandHtmlEntities); + +#endif diff --git a/Source/Doxygen/doxyentity.cxx b/Source/Doxygen/doxyentity.cxx new file mode 100644 index 000000000..8b9f65736 --- /dev/null +++ b/Source/Doxygen/doxyentity.cxx @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * doxyentity.cxx + * + * Part of the Doxygen comment translation module of SWIG. + * ----------------------------------------------------------------------------- */ + +#include "doxyentity.h" +#include + +using std::cout; + +DoxygenEntity::DoxygenEntity(const std::string &typeEnt):typeOfEntity(typeEnt), isLeaf(true) { +} + + +/* Basic node for commands that have + * only 1 item after them + * example: \b word + * OR holding a std::string + */ +DoxygenEntity::DoxygenEntity(const std::string &typeEnt, const std::string ¶m1) : typeOfEntity(typeEnt), data(param1), isLeaf(true) { +} + + +/* Nonterminal node + * contains + */ +DoxygenEntity::DoxygenEntity(const std::string &typeEnt, const DoxygenEntityList &entList) : typeOfEntity(typeEnt), isLeaf(false), entityList(entList) { +} + + +void DoxygenEntity::printEntity(int level) const { + + int thisLevel = level; + + if (isLeaf) { + for (int i = 0; i < thisLevel; i++) { + cout << "\t"; + } + + cout << "Node Leaf Command: '" << typeOfEntity << "', "; + + if (!data.empty()) { + cout << "Node Data: '" << data << "'"; + } + cout << std::endl; + + } else { + + for (int i = 0; i < thisLevel; i++) { + cout << "\t"; + } + + cout << "Node Command: '" << typeOfEntity << "'" << std::endl; + + thisLevel++; + + for (DoxygenEntityListCIt p = entityList.begin(); p != entityList.end(); p++) { + p->printEntity(thisLevel); + } + } +} diff --git a/Source/Doxygen/doxyentity.h b/Source/Doxygen/doxyentity.h new file mode 100644 index 000000000..93737e604 --- /dev/null +++ b/Source/Doxygen/doxyentity.h @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * doxyentity.h + * + * Part of the Doxygen comment translation module of SWIG. + * ----------------------------------------------------------------------------- */ + +#ifndef DOXYGENENTITY_H_ +#define DOXYGENENTITY_H_ + +#include +#include + + +class DoxygenEntity; + +typedef std::list DoxygenEntityList; +typedef DoxygenEntityList::iterator DoxygenEntityListIt; +typedef DoxygenEntityList::const_iterator DoxygenEntityListCIt; + + +/* + * Structure to represent a doxygen comment entry + */ +class DoxygenEntity { +public: + std::string typeOfEntity; + std::string data; + bool isLeaf; + DoxygenEntityList entityList; + + DoxygenEntity(const std::string &typeEnt); + DoxygenEntity(const std::string &typeEnt, const std::string ¶m1); + DoxygenEntity(const std::string &typeEnt, const DoxygenEntityList &entList); + + void printEntity(int level) const; +}; + +#endif diff --git a/Source/Doxygen/doxyparser.cxx b/Source/Doxygen/doxyparser.cxx new file mode 100644 index 000000000..2e826b265 --- /dev/null +++ b/Source/Doxygen/doxyparser.cxx @@ -0,0 +1,1439 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * doxyparser.cxx + * ----------------------------------------------------------------------------- */ + +#include "doxyparser.h" +#include "doxycommands.h" +#include "swig.h" +#include "swigwarn.h" + +#include +#include +#include + +using std::string; +using std::cout; +using std::endl; + +// This constant defines the (only) characters valid inside a Doxygen "word". +// It includes some unusual ones because of the commands such as \f[, \f{, \f], +// \f} and \f$. +static const char *DOXYGEN_WORD_CHARS = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "$[]{}"; + +// Define static class members +DoxygenParser::DoxyCommandsMap DoxygenParser::doxygenCommands; +std::set DoxygenParser::doxygenSectionIndicators; + +const int TOKENSPERLINE = 8; //change this to change the printing behaviour of the token list +const std::string END_HTML_TAG_MARK("/"); + +DoxygenParser::DoxygenParser(bool noisy) : noisy(noisy) { + fillTables(); +} + +DoxygenParser::~DoxygenParser() { +} + +void DoxygenParser::fillTables() { + // run it only once + if (doxygenCommands.size()) + return; + + // fill in tables with data from doxycommands.h + for (int i = 0; i < simpleCommandsSize; i++) + doxygenCommands[simpleCommands[i]] = SIMPLECOMMAND; + + for (int i = 0; i < commandWordsSize; i++) + doxygenCommands[commandWords[i]] = COMMANDWORD; + + for (int i = 0; i < commandLinesSize; i++) + doxygenCommands[commandLines[i]] = COMMANDLINE; + + for (int i = 0; i < commandParagraphSize; i++) + doxygenCommands[commandParagraph[i]] = COMMANDPARAGRAPH; + + for (int i = 0; i < commandEndCommandsSize; i++) + doxygenCommands[commandEndCommands[i]] = COMMANDENDCOMMAND; + + for (int i = 0; i < commandWordParagraphsSize; i++) + doxygenCommands[commandWordParagraphs[i]] = COMMANDWORDPARAGRAPH; + + for (int i = 0; i < commandWordLinesSize; i++) + doxygenCommands[commandWordLines[i]] = COMMANDWORDLINE; + + for (int i = 0; i < commandWordOWordOWordsSize; i++) + doxygenCommands[commandWordOWordOWords[i]] = COMMANDWORDOWORDWORD; + + for (int i = 0; i < commandOWordsSize; i++) + doxygenCommands[commandOWords[i]] = COMMANDOWORD; + + for (int i = 0; i < commandErrorThrowingsSize; i++) + doxygenCommands[commandErrorThrowings[i]] = COMMANDERRORTHROW; + + for (int i = 0; i < commandUniquesSize; i++) + doxygenCommands[commandUniques[i]] = COMMANDUNIQUE; + + for (int i = 0; i < commandHtmlSize; i++) + doxygenCommands[commandHtml[i]] = COMMAND_HTML; + + for (int i = 0; i < commandHtmlEntitiesSize; i++) + doxygenCommands[commandHtmlEntities[i]] = COMMAND_HTML_ENTITY; + + // fill section indicators command set + for (int i = 0; i < sectionIndicatorsSize; i++) + doxygenSectionIndicators.insert(sectionIndicators[i]); +} + +std::string DoxygenParser::stringToLower(const std::string &stringToConvert) { + + string result(stringToConvert.size(), ' '); + + for (size_t i = 0; i < result.size(); i++) { + result[i] = tolower(stringToConvert[i]); + } + + return result; +} + +bool DoxygenParser::isSectionIndicator(const std::string &smallString) { + + std::set::iterator it = doxygenSectionIndicators.find(stringToLower(smallString)); + + return it != doxygenSectionIndicators.end(); +} + +void DoxygenParser::printTree(const DoxygenEntityList &rootList) { + DoxygenEntityList::const_iterator p = rootList.begin(); + while (p != rootList.end()) { + (*p).printEntity(0); + p++; + } +} + +DoxygenParser::DoxyCommandEnum DoxygenParser::commandBelongs(const std::string &theCommand) { + DoxyCommandsMapIt it = doxygenCommands.find(stringToLower(theCommand)); + + if (it != doxygenCommands.end()) { + return it->second; + } + // Check if this command is defined as an alias. + if (Getattr(m_node, ("feature:doxygen:alias:" + theCommand).c_str())) { + return COMMAND_ALIAS; + } + // Check if this command should be ignored. + if (String *const ignore = getIgnoreFeature(theCommand)) { + // Check that no value is specified for this feature ("1" is the implicit + // one given to it by SWIG itself), we may use the value in the future, but + // for now we only use the attributes. + if (Strcmp(ignore, "1") != 0) { + Swig_warning(WARN_PP_UNEXPECTED_TOKENS, m_fileName.c_str(), m_fileLineNo, + "Feature \"doxygen:ignore\" value ignored for Doxygen command \"%s\".\n", theCommand.c_str()); + } + // Also ensure that the matching end command, if any, will be recognized. + const string endCommand = getIgnoreFeatureEndCommand(theCommand); + if (!endCommand.empty()) { + Setattr(m_node, ("feature:doxygen:ignore:" + endCommand).c_str(), NewString("1")); + } + + return COMMAND_IGNORE; + } + + return NONE; +} + +std::string DoxygenParser::trim(const std::string &text) { + size_t start = text.find_first_not_of(" \t"); + size_t end = text.find_last_not_of(" \t"); + + if (start == string::npos || start > end) { + return ""; + } + return text.substr(start, end - start + 1); +} + +bool DoxygenParser::isEndOfLine() { + if (m_tokenListIt == m_tokenList.end()) { + return false; + } + Token nextToken = *m_tokenListIt; + return nextToken.m_tokenType == END_LINE; +} + +void DoxygenParser::skipWhitespaceTokens() { + if (m_tokenListIt == m_tokenList.end()) { + return; + } + + while (m_tokenListIt != m_tokenList.end() + && (m_tokenListIt->m_tokenType == END_LINE || trim(m_tokenListIt->m_tokenString).empty())) { + + m_tokenListIt++; + } +} + +std::string DoxygenParser::getNextToken() { + + if (m_tokenListIt == m_tokenList.end()) { + return ""; + } + + if (m_tokenListIt->m_tokenType == PLAINSTRING) { + return (m_tokenListIt++)->m_tokenString; + } + + return ""; +} + +std::string DoxygenParser::getNextWord() { + + /* if (m_tokenListIt == m_tokenList.end()) { + return ""; + } + */ + while (m_tokenListIt != m_tokenList.end() + && (m_tokenListIt->m_tokenType == PLAINSTRING)) { + // handle quoted strings as words + string token = m_tokenListIt->m_tokenString; + if (token == "\"") { + + string word = m_tokenListIt->m_tokenString; + m_tokenListIt++; + while (true) { + string nextWord = getNextToken(); + if (nextWord.empty()) { // maybe report unterminated string error + return word; + } + word += nextWord; + if (nextWord == "\"") { + return word; + } + } + } + + string tokenStr = trim(m_tokenListIt->m_tokenString); + m_tokenListIt++; + if (!tokenStr.empty()) { + return tokenStr; + } + } + + return ""; +} + +DoxygenParser::TokenListCIt DoxygenParser::getOneLine(const TokenList &tokList) { + + TokenListCIt endOfLineIt = m_tokenListIt; + + while (endOfLineIt != tokList.end()) { + if (endOfLineIt->m_tokenType == END_LINE) { + return endOfLineIt; + } + endOfLineIt++; + } + + return tokList.end(); +} + +std::string DoxygenParser::getStringTilCommand(const TokenList &tokList) { + + if (m_tokenListIt == tokList.end()) { + return ""; + } + + string description; + + while (m_tokenListIt->m_tokenType == PLAINSTRING) { + const Token ¤tToken = *m_tokenListIt++; + if (currentToken.m_tokenType == PLAINSTRING) { + description = description + currentToken.m_tokenString; // + " "; + } + } + return description; +} + +std::string DoxygenParser::getStringTilEndCommand(const std::string &theCommand, const TokenList &tokList) { + + if (m_tokenListIt == tokList.end()) { + return ""; + } + + string description; + while (m_tokenListIt != tokList.end()) { + + if (m_tokenListIt->m_tokenType == PLAINSTRING) { + description += m_tokenListIt->m_tokenString; + } else if (m_tokenListIt->m_tokenType == END_LINE) { + description += "\n"; + } else if (m_tokenListIt->m_tokenString == theCommand) { + m_tokenListIt++; + return description; + } + + m_tokenListIt++; + } + + printListError(WARN_DOXYGEN_COMMAND_EXPECTED, "Expected Doxygen command: " + theCommand + "."); + + return description; +} + +DoxygenParser::TokenListCIt DoxygenParser::getEndOfParagraph(const TokenList &tokList) { + + TokenListCIt endOfParagraph = m_tokenListIt; + + while (endOfParagraph != tokList.end()) { + // If \code or \verbatim is encountered within a paragraph, then + // go all the way to the end of that command, since the content + // could contain empty lines that would appear to be paragraph + // ends: + if (endOfParagraph->m_tokenType == COMMAND && + (endOfParagraph->m_tokenString == "code" || + endOfParagraph->m_tokenString == "verbatim")) { + const string theCommand = endOfParagraph->m_tokenString; + endOfParagraph = getEndCommand("end" + theCommand, tokList); + endOfParagraph++; // Move after the end command + return endOfParagraph; + } + if (endOfParagraph->m_tokenType == END_LINE) { + endOfParagraph++; + if (endOfParagraph != tokList.end() + && endOfParagraph->m_tokenType == END_LINE) { + endOfParagraph++; + //cout << "ENCOUNTERED END OF PARA" << endl; + return endOfParagraph; + } + + } else if (endOfParagraph->m_tokenType == COMMAND) { + + if (isSectionIndicator(endOfParagraph->m_tokenString)) { + return endOfParagraph; + } else { + endOfParagraph++; + } + + } else if (endOfParagraph->m_tokenType == PLAINSTRING) { + endOfParagraph++; + } else { + return tokList.end(); + } + } + + return tokList.end(); +} + +DoxygenParser::TokenListCIt DoxygenParser::getEndOfSection(const std::string &theCommand, const TokenList &tokList) { + + TokenListCIt endOfParagraph = m_tokenListIt; + + while (endOfParagraph != tokList.end()) { + if (endOfParagraph->m_tokenType == COMMAND) { + if (theCommand == endOfParagraph->m_tokenString) + return endOfParagraph; + else + endOfParagraph++; + } else if (endOfParagraph->m_tokenType == PLAINSTRING) { + endOfParagraph++; + } else if (endOfParagraph->m_tokenType == END_LINE) { + endOfParagraph++; + if (endOfParagraph->m_tokenType == END_LINE) { + endOfParagraph++; + return endOfParagraph; + } + } + } + return tokList.end(); +} + +DoxygenParser::TokenListCIt DoxygenParser::getEndCommand(const std::string &theCommand, const TokenList &tokList) { + + TokenListCIt endOfCommand = m_tokenListIt; + + while (endOfCommand != tokList.end()) { + endOfCommand++; + if ((*endOfCommand).m_tokenType == COMMAND) { + if (theCommand == (*endOfCommand).m_tokenString) { + return endOfCommand; + } + } + } + //End command not found + return tokList.end(); +} + +void DoxygenParser::skipEndOfLine() { + if (m_tokenListIt != m_tokenList.end() + && m_tokenListIt->m_tokenType == END_LINE) { + m_tokenListIt++; + } +} + +void DoxygenParser::addSimpleCommand(const std::string &theCommand, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + + doxyList.push_back(DoxygenEntity(theCommand)); +} + +void DoxygenParser::addCommandWord(const std::string &theCommand, const TokenList &, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + + if (isEndOfLine()) { + // handles cases when command is at the end of line (for example "\c\nreally" + skipWhitespaceTokens(); + doxyList.push_back(DoxygenEntity("plainstd::endl")); + } + std::string name = getNextWord(); + if (!name.empty()) { + DoxygenEntityList aNewList; + aNewList.push_back(DoxygenEntity("plainstd::string", name)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } else { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored."); + } +} + +void DoxygenParser::addCommandLine(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + TokenListCIt endOfLine = getOneLine(tokList); + DoxygenEntityList aNewList = parse(endOfLine, tokList); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + skipEndOfLine(); +} + +void DoxygenParser::addCommandParagraph(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + + TokenListCIt endOfParagraph = getEndOfParagraph(tokList); + DoxygenEntityList aNewList; + aNewList = parse(endOfParagraph, tokList); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); +} + +void DoxygenParser::addCommandEndCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + TokenListCIt endCommand = getEndCommand("end" + theCommand, tokList); + if (endCommand == tokList.end()) { + printListError(WARN_DOXYGEN_COMMAND_EXPECTED, "Expected Doxygen command: end" + theCommand + "."); + return; + } + DoxygenEntityList aNewList; + aNewList = parse(endCommand, tokList); + m_tokenListIt++; + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); +} + +void DoxygenParser::addCommandWordParagraph(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + + std::string name = getNextWord(); + + if (name.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored."); + return; + } + TokenListCIt endOfParagraph = getEndOfParagraph(tokList); + DoxygenEntityList aNewList; + aNewList = parse(endOfParagraph, tokList); + aNewList.push_front(DoxygenEntity("plainstd::string", name)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); +} + +void DoxygenParser::addCommandWordLine(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + std::string name = getNextWord(); + if (name.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored."); + return; + } + + TokenListCIt endOfLine = getOneLine(tokList); + DoxygenEntityList aNewList; + aNewList = parse(endOfLine, tokList); + aNewList.push_front(DoxygenEntity("plainstd::string", name)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + //else cout << "No line followed " << theCommand << " command. Not added" << endl; +} + +void DoxygenParser::addCommandWordOWordOWord(const std::string &theCommand, const TokenList &, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + + std::string name = getNextWord(); + if (name.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored."); + return; + } + std::string headerfile = getNextWord(); + std::string headername = getNextWord(); + DoxygenEntityList aNewList; + aNewList.push_back(DoxygenEntity("plainstd::string", name)); + if (!headerfile.empty()) + aNewList.push_back(DoxygenEntity("plainstd::string", headerfile)); + if (!headername.empty()) + aNewList.push_back(DoxygenEntity("plainstd::string", headername)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); +} + +void DoxygenParser::addCommandOWord(const std::string &theCommand, const TokenList &, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + + std::string name = getNextWord(); + DoxygenEntityList aNewList; + aNewList.push_back(DoxygenEntity("plainstd::string", name)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); +} + +void DoxygenParser::addCommandErrorThrow(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &) { + + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": Unexpectedly encountered this command."); + m_tokenListIt = getOneLine(tokList); +} + +void DoxygenParser::addCommandHtml(const std::string &theCommand, const TokenList &, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + + std::string htmlTagArgs = getNextToken(); + doxyList.push_back(DoxygenEntity(theCommand, htmlTagArgs)); +} + +void DoxygenParser::addCommandHtmlEntity(const std::string &theCommand, const TokenList &, DoxygenEntityList &doxyList) { + if (noisy) + cout << "Parsing " << theCommand << endl; + + DoxygenEntityList aNewList; + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); +} + +void DoxygenParser::addCommandUnique(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) { + + static std::map endCommands; + DoxygenEntityList aNewList; + if (theCommand == "arg" || theCommand == "li") { + TokenListCIt endOfSection = getEndOfSection(theCommand, tokList); + DoxygenEntityList aNewList; + aNewList = parse(endOfSection, tokList); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \xrefitem "(heading)" "(std::list title)" {text} + else if (theCommand == "xrefitem") { + if (noisy) + cout << "Parsing " << theCommand << endl; + std::string key = getNextWord(); + if (key.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No key followed the command. Command ignored."); + return; + } + std::string heading = getNextWord(); + if (key.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No heading followed the command. Command ignored."); + return; + } + std::string title = getNextWord(); + if (title.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No title followed the command. Command ignored."); + return; + } + TokenListCIt endOfParagraph = getEndOfParagraph(tokList); + aNewList = parse(endOfParagraph, tokList); + aNewList.push_front(DoxygenEntity("plainstd::string", title)); + aNewList.push_front(DoxygenEntity("plainstd::string", heading)); + aNewList.push_front(DoxygenEntity("plainstd::string", key)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \ingroup ( [ ]) + else if (theCommand == "ingroup") { + std::string name = getNextWord(); + aNewList.push_back(DoxygenEntity("plainstd::string", name)); + name = getNextWord(); + if (!name.empty()) + aNewList.push_back(DoxygenEntity("plainstd::string", name)); + name = getNextWord(); + if (!name.empty()) + aNewList.push_back(DoxygenEntity("plainstd::string", name)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \par [(paragraph title)] { paragraph } + else if (theCommand == "par") { + TokenListCIt endOfLine = getOneLine(tokList); + aNewList = parse(endOfLine, tokList); + DoxygenEntityList aNewList2; + TokenListCIt endOfParagraph = getEndOfParagraph(tokList); + aNewList2 = parse(endOfParagraph, tokList); + aNewList.splice(aNewList.end(), aNewList2); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \headerfile [] + else if (theCommand == "headerfile") { + DoxygenEntityList aNewList; + std::string name = getNextWord(); + aNewList.push_back(DoxygenEntity("plainstd::string", name)); + name = getNextWord(); + if (!name.empty()) + aNewList.push_back(DoxygenEntity("plainstd::string", name)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \overload [(function declaration)] + else if (theCommand == "overload") { + TokenListCIt endOfLine = getOneLine(tokList); + if (endOfLine != m_tokenListIt) { + DoxygenEntityList aNewList; + aNewList = parse(endOfLine, tokList); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } else + doxyList.push_back(DoxygenEntity(theCommand)); + } + // \weakgroup [(title)] + else if (theCommand == "weakgroup") { + if (noisy) + cout << "Parsing " << theCommand << endl; + std::string name = getNextWord(); + if (name.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored."); + return; + } + DoxygenEntityList aNewList; + TokenListCIt endOfLine = getOneLine(tokList); + if (endOfLine != m_tokenListIt) { + aNewList = parse(endOfLine, tokList); + } + aNewList.push_front(DoxygenEntity("plainstd::string", name)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \ref ["(text)"] + else if (theCommand == "ref") { + if (noisy) + cout << "Parsing " << theCommand << endl; + std::string name = getNextWord(); + if (name.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No key followed the command. Command ignored."); + return; + } + DoxygenEntityList aNewList; + aNewList.push_front(DoxygenEntity("plainstd::string", name)); + // TokenListCIt endOfLine = getOneLine(tokList); + // if (endOfLine != m_tokenListIt) { + // aNewList = parse(endOfLine, tokList); + //} + TokenListCIt tmpIt = m_tokenListIt; + std::string refTitle = getNextWord(); + // If title is following the ref tag, it must be quoted. Otherwise + // doxy puts link on ref id. + if (refTitle.size() > 1 && refTitle[0] == '"') { + // remove quotes + refTitle = refTitle.substr(1, refTitle.size() - 2); + aNewList.push_back(DoxygenEntity("plainstd::string", refTitle)); + } else { + // no quoted string is following, so we have to restore iterator + m_tokenListIt = tmpIt; + } + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \subpage ["(text)"] + else if (theCommand == "subpage") { + if (noisy) + cout << "Parsing " << theCommand << endl; + std::string name = getNextWord(); + if (name.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No name followed the command. Command ignored."); + return; + } + std::string text = getNextWord(); + aNewList.push_back(DoxygenEntity("plainstd::string", name)); + if (!text.empty()) + aNewList.push_back(DoxygenEntity("plainstd::string", text)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \code ... \endcode + // \verbatim ... \endverbatim + // \dot dotcode \enddot + // \msc msccode \endmsc + // \f[ ... \f] + // \f{ ... \f} + // \f{env}{ ... \f} + // \f$ ... \f$ + else if (theCommand == "code" || theCommand == "verbatim" + || theCommand == "dot" || theCommand == "msc" || theCommand == "f[" || theCommand == "f{" || theCommand == "f$") { + if (!endCommands.size()) { + // fill in static table of end commands + endCommands["f["] = "f]"; + endCommands["f{"] = "f}"; + endCommands["f$"] = "f$"; + } + if (noisy) + cout << "Parsing " << theCommand << endl; + + std::string endCommand; + std::map::iterator it; + it = endCommands.find(theCommand); + if (it != endCommands.end()) + endCommand = it->second; + else + endCommand = "end" + theCommand; + + std::string content = getStringTilEndCommand(endCommand, tokList); + aNewList.push_back(DoxygenEntity("plainstd::string", content)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \dotfile ["caption"] + // \mscfile ["caption"] + else if (theCommand == "dotfile" || theCommand == "mscfile") { + if (noisy) + cout << "Parsing " << theCommand << endl; + std::string file = getNextWord(); + if (file.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No file followed the command. Command ignored."); + return; + } + std::string caption = getNextWord(); + aNewList.push_back(DoxygenEntity("plainstd::string", file)); + if (!caption.empty()) + aNewList.push_back(DoxygenEntity("plainstd::string", caption)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \image ["caption"] [=] + else if (theCommand == "image") { + if (noisy) + cout << "Parsing " << theCommand << endl; + std::string format = getNextWord(); + if (format.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No format followed the command. Command ignored."); + return; + } + std::string file = getNextWord(); + if (file.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No name followed the command. Command ignored."); + return; + } + std::string caption = getNextWord(); + std::string size = getNextWord(); + + DoxygenEntityList aNewList; + aNewList.push_back(DoxygenEntity("plainstd::string", format)); + aNewList.push_back(DoxygenEntity("plainstd::string", file)); + if (!caption.empty()) + aNewList.push_back(DoxygenEntity("plainstd::string", caption)); + if (!size.empty()) + aNewList.push_back(DoxygenEntity("plainstd::string", size)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } + // \addtogroup [(title)] + else if (theCommand == "addtogroup") { + if (noisy) + cout << "Parsing " << theCommand << endl; + std::string name = getNextWord(); + if (name.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": There should be at least one word following the command. Command ignored."); + return; + } + DoxygenEntityList aNewList; + TokenListCIt endOfLine = getOneLine(tokList); + if (endOfLine != m_tokenListIt) { + aNewList = parse(endOfLine, tokList); + } + aNewList.push_front(DoxygenEntity("plainstd::string", name)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + skipEndOfLine(); + } + // \if [\else ...] [\elseif ...] \endif + else if (theCommand == "if" || theCommand == "ifnot" || theCommand == "else" || theCommand == "elseif") { + if (noisy) + cout << "Parsing " << theCommand << endl; + + std::string cond; + bool skipEndif = false; // if true then we skip endif after parsing block of code + bool needsCond = (theCommand == "if" || theCommand == "ifnot" || theCommand == "elseif"); + if (needsCond) { + cond = getNextWord(); + if (cond.empty()) { + printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored."); + return; + } + } + + int nestedCounter = 1; + TokenListCIt endCommand = tokList.end(); + + // go through the commands and find closing endif or else or elseif + for (TokenListCIt it = m_tokenListIt; it != tokList.end(); it++) { + if (it->m_tokenType == COMMAND) { + if (it->m_tokenString == "if" || it->m_tokenString == "ifnot") + nestedCounter++; + else if (it->m_tokenString == "endif") + nestedCounter--; + if (nestedCounter == 1 && (it->m_tokenString == "else" || it->m_tokenString == "elseif")) { // else found + endCommand = it; + break; + } + if (nestedCounter == 0) { // endif found + endCommand = it; + skipEndif = true; + break; + } + } + } + + if (endCommand == tokList.end()) { + printListError(WARN_DOXYGEN_COMMAND_EXPECTED, "Expected Doxygen command: endif."); + return; + } + + DoxygenEntityList aNewList; + aNewList = parse(endCommand, tokList); + if (skipEndif) + m_tokenListIt++; + if (needsCond) + aNewList.push_front(DoxygenEntity("plainstd::string", cond)); + doxyList.push_back(DoxygenEntity(theCommand, aNewList)); + } +} + +void DoxygenParser::aliasCommand(const std::string &theCommand, const TokenList &/* tokList */ , DoxygenEntityList &doxyList) { + String *const alias = Getattr(m_node, ("feature:doxygen:alias:" + theCommand).c_str()); + if (!alias) + return; + + doxyList.push_back(DoxygenEntity("plainstd::string", Char(alias))); +} + +String *DoxygenParser::getIgnoreFeature(const std::string &theCommand, const char *argument) const { + string feature_name = "feature:doxygen:ignore:" + theCommand; + if (argument) { + feature_name += ':'; + feature_name += argument; + } + + return Getattr(m_node, feature_name.c_str()); +} + +string DoxygenParser::getIgnoreFeatureEndCommand(const std::string &theCommand) const { + // We may be dealing either with a simple command or with the starting command + // of a block, as indicated by the value of "range" starting with "end". + string endCommand; + if (String *const range = getIgnoreFeature(theCommand, "range")) { + const char *const p = Char(range); + if (strncmp(p, "end", 3) == 0) { + if (p[3] == ':') { + // Normally the end command name follows after the colon. + endCommand = p + 4; + } else if (p[3] == '\0') { + // But it may be omitted in which case the default Doxygen convention of + // using "something"/"endsomething" is used. + endCommand = "end" + theCommand; + } + } + } + + return endCommand; +} + +void DoxygenParser::ignoreCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) { + const string endCommand = getIgnoreFeatureEndCommand(theCommand); + if (!endCommand.empty()) { + TokenListCIt itEnd = getEndCommand(endCommand, tokList); + if (itEnd == tokList.end()) { + printListError(WARN_DOXYGEN_COMMAND_EXPECTED, "Expected Doxygen command: " + endCommand + "."); + return; + } + // If we ignore the command, also ignore any whitespace preceding it as we + // want to avoid having lines consisting of whitespace only or trailing + // whitespace in general (at least Python, with its pep8 tool, really + // doesn't like it). + if (!doxyList.empty()) { + DoxygenEntityList::iterator i = doxyList.end(); + --i; + if (i->typeOfEntity == "plainstd::string" && i->data.find_first_not_of(" \t") == std::string::npos) { + doxyList.erase(i); + } + } + // Determine what to do with the part of the comment between the start and + // end commands: by default, we simply throw it away, but "contents" + // attribute may be used to change this. + if (String *const contents = getIgnoreFeature(theCommand, "contents")) { + // Currently only "parse" is supported but we may need to add "copy" to + // handle custom tags which contain text that is supposed to be copied + // verbatim in the future. + if (Strcmp(contents, "parse") == 0) { + DoxygenEntityList aNewList = parse(itEnd, tokList); + doxyList.splice(doxyList.end(), aNewList); + } else { + Swig_error(m_fileName.c_str(), m_fileLineNo, "Invalid \"doxygen:ignore\" feature \"contents\" attribute \"%s\".\n", Char(contents)); + return; + } + } + + m_tokenListIt = itEnd; + m_tokenListIt++; + } else if (String *const range = getIgnoreFeature(theCommand, "range")) { + // Currently we only support "line" but, in principle, we should also + // support "word" and "paragraph" for consistency with the built-in Doxygen + // commands which can have either of these three ranges (which are indicated + // using , (line-arg) and {para-arg} respectively in Doxygen + // documentation). + if (Strcmp(range, "line") == 0) { + // Consume everything until the end of line. + m_tokenListIt = getOneLine(tokList); + skipEndOfLine(); + } else { + Swig_error(m_fileName.c_str(), m_fileLineNo, "Invalid \"doxygen:ignore\" feature \"range\" attribute \"%s\".\n", Char(range)); + return; + } + } +} + +void DoxygenParser::addCommand(const std::string &commandString, const TokenList &tokList, DoxygenEntityList &doxyList) { + + string theCommand = stringToLower(commandString); + + if (theCommand == "plainstd::string") { + string nextPhrase = getStringTilCommand(tokList); + if (noisy) + cout << "Parsing plain std::string :" << nextPhrase << endl; + doxyList.push_back(DoxygenEntity("plainstd::string", nextPhrase)); + return; + } + + switch (commandBelongs(commandString)) { + case SIMPLECOMMAND: + addSimpleCommand(theCommand, doxyList); + break; + case COMMANDWORD: + addCommandWord(theCommand, tokList, doxyList); + break; + case COMMANDLINE: + addCommandLine(theCommand, tokList, doxyList); + break; + case COMMANDPARAGRAPH: + addCommandParagraph(theCommand, tokList, doxyList); + break; + case COMMANDENDCOMMAND: + addCommandEndCommand(theCommand, tokList, doxyList); + break; + case COMMANDWORDPARAGRAPH: + addCommandWordParagraph(theCommand, tokList, doxyList); + break; + case COMMANDWORDLINE: + addCommandWordLine(theCommand, tokList, doxyList); + break; + case COMMANDWORDOWORDWORD: + addCommandWordOWordOWord(theCommand, tokList, doxyList); + break; + case COMMANDOWORD: + addCommandOWord(theCommand, tokList, doxyList); + break; + case COMMANDERRORTHROW: + addCommandErrorThrow(theCommand, tokList, doxyList); + break; + case COMMANDUNIQUE: + addCommandUnique(theCommand, tokList, doxyList); + break; + case COMMAND_HTML: + addCommandHtml(theCommand, tokList, doxyList); + break; + case COMMAND_HTML_ENTITY: + addCommandHtmlEntity(theCommand, tokList, doxyList); + break; + case COMMAND_ALIAS: + aliasCommand(commandString, tokList, doxyList); + break; + case COMMAND_IGNORE: + ignoreCommand(commandString, tokList, doxyList); + break; + case NONE: + case END_LINE: + case PARAGRAPH_END: + case PLAINSTRING: + case COMMAND: + // TODO: Ensure that these values either are correctly ignored here or can't happen. + break; + } +} + +/** + * This method converts TokenList to DoxygenEntryList. + */ +DoxygenEntityList DoxygenParser::parse(TokenListCIt endParsingIndex, const TokenList &tokList, bool root) { + // if we are root, than any strings should be added as 'partofdescription', else as 'plainstd::string' + std::string currPlainstringCommandType = root ? "partofdescription" : "plainstd::string"; + DoxygenEntityList aNewList; + + // Less than check (instead of not equal) is a safeguard in case the + // iterator is incremented past the end + while (m_tokenListIt < endParsingIndex) { + + Token currToken = *m_tokenListIt; + + if (noisy) + cout << "Parsing for phrase starting in:" << currToken.toString() << endl; + + if (currToken.m_tokenType == END_LINE) { + aNewList.push_back(DoxygenEntity("plainstd::endl")); + m_tokenListIt++; + } else if (currToken.m_tokenType == COMMAND) { + m_tokenListIt++; + addCommand(currToken.m_tokenString, tokList, aNewList); + } else if (currToken.m_tokenType == PLAINSTRING) { + addCommand(currPlainstringCommandType, tokList, aNewList); + } + + // If addCommand above misbehaves, it can move the iterator past endParsingIndex + if (m_tokenListIt > endParsingIndex) + printListError(WARN_DOXYGEN_UNEXPECTED_ITERATOR_VALUE, "Unexpected iterator value in DoxygenParser::parse"); + + if (endParsingIndex != tokList.end() && m_tokenListIt == tokList.end()) { + // this could happen if we can't reach the original endParsingIndex + printListError(WARN_DOXYGEN_UNEXPECTED_END_OF_COMMENT, "Unexpected end of Doxygen comment encountered."); + break; + } + } + return aNewList; +} + +DoxygenEntityList DoxygenParser::createTree(Node *node, String *documentation) { + m_node = node; + + tokenizeDoxygenComment(Char(documentation), Char(Getfile(documentation)), Getline(documentation)); + + if (noisy) { + cout << "---TOKEN LIST---" << endl; + printList(); + } + + DoxygenEntityList rootList = parse(m_tokenList.end(), m_tokenList, true); + + if (noisy) { + cout << "PARSED LIST" << endl; + printTree(rootList); + } + return rootList; +} + +/* + * Splits 'text' on 'separator' chars. Separator chars are not part of the + * strings. + */ +DoxygenParser::StringVector DoxygenParser::split(const std::string &text, char separator) { + StringVector lines; + size_t prevPos = 0, pos = 0; + + while (pos < string::npos) { + pos = text.find(separator, prevPos); + lines.push_back(text.substr(prevPos, pos - prevPos)); + prevPos = pos + 1; + } + + return lines; +} + +/* + * Returns true, if 'c' is one of doxygen comment block start + * characters: *, /, or ! + */ +bool DoxygenParser::isStartOfDoxyCommentChar(char c) { + return (strchr("*/!", c) != NULL); +} + +/* + * Adds token with Doxygen command to token list, but only if command is one of + * Doxygen commands. In that case true is returned. If the command is not + * recognized as a doxygen command, it is ignored and false is returned. + */ +bool DoxygenParser::addDoxyCommand(DoxygenParser::TokenList &tokList, const std::string &cmd) { + if (commandBelongs(cmd) != NONE) { + tokList.push_back(Token(COMMAND, cmd)); + return true; + } else { + // This function is called for the special Doxygen commands, but also for + // HTML commands (or anything that looks like them, actually) and entities. + // We don't recognize all of those, so just ignore them and pass them + // through, but warn about unknown Doxygen commands as ignoring them will + // often result in wrong output being generated. + const char ch = *cmd.begin(); + if (ch != '<' && ch != '&') { + // Before calling printListError() we must ensure that m_tokenListIt used + // by it is valid. + const TokenListCIt itSave = m_tokenListIt; + m_tokenListIt = m_tokenList.end(); + + printListError(WARN_DOXYGEN_UNKNOWN_COMMAND, "Unknown Doxygen command: " + cmd + "."); + + m_tokenListIt = itSave; + } + } + + return false; +} + +/* + * This method copies comment text to output as it is - no processing is + * done, Doxygen commands are ignored. It is used for commands \verbatim, + * \htmlonly, \f$, \f[, and \f{. + */ +size_t DoxygenParser::processVerbatimText(size_t pos, const std::string &line) { + if (line[pos] == '\\' || line[pos] == '@') { // check for end commands + + pos++; + size_t endOfWordPos = line.find_first_not_of(DOXYGEN_WORD_CHARS, pos); + string cmd = line.substr(pos, endOfWordPos - pos); + + if (cmd == CMD_END_HTML_ONLY || cmd == CMD_END_VERBATIM || cmd == CMD_END_LATEX_1 || cmd == CMD_END_LATEX_2 || cmd == CMD_END_LATEX_3) { + + m_isVerbatimText = false; + addDoxyCommand(m_tokenList, cmd); + + } else { + + m_tokenList.push_back(Token(PLAINSTRING, + // include '\' or '@' + line.substr(pos - 1, endOfWordPos - pos + 1))); + } + + pos = endOfWordPos; + + } else { + + // whitespaces are stored as plain strings + size_t startOfPossibleEndCmd = line.find_first_of("\\@", pos); + m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, startOfPossibleEndCmd - pos))); + pos = startOfPossibleEndCmd; + } + + return pos; +} + +/* + * Processes doxy commands for escaped characters: \$ \@ \\ \& \~ \< \> \# \% \" \. \:: + * Handling this separately supports documentation text like \@someText. + */ +bool DoxygenParser::processEscapedChars(size_t &pos, const std::string &line) { + if ((pos + 1) < line.size()) { + + // \ and @ with trailing whitespace or quoted get to output as plain string + string whitespaces = " '\t\n"; + if (whitespaces.find(line[pos + 1]) != string::npos) { + m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, 1))); + pos++; + return true; + } + // these chars can be escaped for doxygen + string escapedChars = "$@\\&~<>#%\"."; + if (escapedChars.find(line[pos + 1]) != string::npos) { + + addDoxyCommand(m_tokenList, line.substr(pos + 1, 1)); + pos += 2; + return true; + + } else if ((pos + 2) < line.size() && line[pos + 1] == ':' && line[pos + 2] == ':') { + + // add command \:: - handling this separately supports documentation + // text like \::someText + addDoxyCommand(m_tokenList, line.substr(pos + 1, 2)); + pos += 3; + return true; + } + } + return false; +} + +/* + * Processes word doxygen commands, like \arg, \c, \b, \return, ... + */ +void DoxygenParser::processWordCommands(size_t &pos, const std::string &line) { + pos++; + size_t endOfWordPos = line.find_first_not_of(DOXYGEN_WORD_CHARS, pos); + + string cmd = line.substr(pos, endOfWordPos - pos); + addDoxyCommand(m_tokenList, cmd); + + if (cmd == CMD_HTML_ONLY || cmd == CMD_VERBATIM || cmd == CMD_LATEX_1 || cmd == CMD_LATEX_2 || cmd == CMD_LATEX_3) { + + m_isVerbatimText = true; + + } else { + // skip any possible spaces after command, because some commands have parameters, + // and spaces between command and parameter must be ignored. + if (endOfWordPos != string::npos) { + endOfWordPos = line.find_first_not_of(" \t", endOfWordPos); + } + } + pos = endOfWordPos; +} + +void DoxygenParser::processHtmlTags(size_t &pos, const std::string &line) { + bool isEndHtmlTag = false; + pos++; + if (line.size() > pos && line[pos] == '/') { + isEndHtmlTag = true; + pos++; + } + + size_t endHtmlPos = line.find_first_of("\t >", pos); + + string cmd = line.substr(pos, endHtmlPos - pos); + pos = endHtmlPos; + + // prepend '<' to distinguish HTML tags from doxygen commands + if (!cmd.empty() && addDoxyCommand(m_tokenList, '<' + cmd)) { + // it is a valid HTML command + if (line[pos] != '>') { + // it should be HTML tag with args, + // for example , , ... + if (isEndHtmlTag) { + m_tokenListIt = m_tokenList.end(); + printListError(WARN_DOXYGEN_HTML_ERROR, "Doxygen HTML error for tag " + cmd + ": Illegal end HTML tag without '>' found."); + } + + endHtmlPos = line.find(">", pos); + if (endHtmlPos == string::npos) { + m_tokenListIt = m_tokenList.end(); + printListError(WARN_DOXYGEN_HTML_ERROR, "Doxygen HTML error for tag " + cmd + ": HTML tag without '>' found."); + } + // add args of HTML command, like link URL, image URL, ... + m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, endHtmlPos - pos))); + pos = endHtmlPos; + } else { + if (isEndHtmlTag) { + m_tokenList.push_back(Token(PLAINSTRING, END_HTML_TAG_MARK)); + } else { + // it is a simple tag, so push empty string + m_tokenList.push_back(Token(PLAINSTRING, "")); + } + } + + if (pos != string::npos) { + pos++; // skip '>' + } + } else { + // the command is not HTML supported by Doxygen, < and > will be + // replaced by HTML entities < and > respectively, + addDoxyCommand(m_tokenList, "<"); + m_tokenList.push_back(Token(PLAINSTRING, cmd)); + } +} + +void DoxygenParser::processHtmlEntities(size_t &pos, const std::string &line) { + size_t endOfWordPos = line.find_first_not_of("abcdefghijklmnopqrstuvwxyz", pos + 1); + + if (endOfWordPos != string::npos) { + + if (line[endOfWordPos] == ';' && (endOfWordPos - pos) > 1) { + // if entity is not recognized by Doxygen (not in the list of + // commands) nothing is added (here and in Doxygen). + addDoxyCommand(m_tokenList, line.substr(pos, endOfWordPos - pos)); + endOfWordPos++; // skip ';' + } else { + // it is not an entity - add entity for ampersand and the rest of string + addDoxyCommand(m_tokenList, "&"); + m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos + 1, endOfWordPos - pos - 1))); + } + } + pos = endOfWordPos; +} + +/* + * This method processes normal comment, which has to be tokenized. + */ +size_t DoxygenParser::processNormalComment(size_t pos, const std::string &line) { + switch (line[pos]) { + case '\\': + case '@': + if (processEscapedChars(pos, line)) { + break; + } + // handle word commands \arg, \c, \return, ... and \f[, \f$, ... commands + processWordCommands(pos, line); + break; + + case ' ': // whitespace + case '\t': + { + // whitespaces are stored as plain strings + size_t startOfNextWordPos = line.find_first_not_of(" \t", pos + 1); + m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, startOfNextWordPos - pos))); + pos = startOfNextWordPos; + } + break; + + case '<': + processHtmlTags(pos, line); + break; + case '>': // this char is detected here only when it is not part of HTML tag + addDoxyCommand(m_tokenList, ">"); + pos++; + break; + case '&': + processHtmlEntities(pos, line); + break; + case '"': + m_isInQuotedString = true; + m_tokenList.push_back(Token(PLAINSTRING, "\"")); + pos++; + break; + default: + m_tokenListIt = m_tokenList.end(); + printListError(WARN_DOXYGEN_UNKNOWN_CHARACTER, std::string("Unknown special character in Doxygen comment: ") + line[pos] + "."); + } + + return pos; +} + +/* + * This is the main method, which tokenizes Doxygen comment to words and + * doxygen commands. + */ +void DoxygenParser::tokenizeDoxygenComment(const std::string &doxygenComment, const std::string &fileName, int fileLine) { + m_isVerbatimText = false; + m_isInQuotedString = false; + m_tokenList.clear(); + m_fileLineNo = fileLine; + m_fileName = fileName; + + StringVector lines = split(doxygenComment, '\n'); + + // remove trailing spaces, because they cause additional new line at the end + // comment, which is wrong, because these spaces are space preceding + // end of comment : ' */' + if (!doxygenComment.empty() && doxygenComment[doxygenComment.size() - 1] == ' ') { + + string lastLine = lines[lines.size() - 1]; + + if (trim(lastLine).empty()) { + lines.pop_back(); // remove trailing empty line + } + } + + for (StringVectorCIt it = lines.begin(); it != lines.end(); it++) { + const string &line = *it; + size_t pos = line.find_first_not_of(" \t"); + + if (pos == string::npos) { + m_tokenList.push_back(Token(END_LINE, "\n")); + continue; + } + // skip sequences of '*', '/', and '!' of any length + bool isStartOfCommentLineCharFound = false; + while (pos < line.size() && isStartOfDoxyCommentChar(line[pos])) { + pos++; + isStartOfCommentLineCharFound = true; + } + + if (pos == line.size()) { + m_tokenList.push_back(Token(END_LINE, "\n")); + continue; + } + // if 'isStartOfCommentLineCharFound' then preserve leading spaces, so + // ' * comment' gets translated to ' * comment', not ' * comment' + // This is important to keep formatting for comments translated to Python. + if (isStartOfCommentLineCharFound && line[pos] == ' ') { + pos++; // points to char after ' * ' + if (pos == line.size()) { + m_tokenList.push_back(Token(END_LINE, "\n")); + continue; + } + } + // line[pos] may be ' \t' or start of word, it there was no '*', '/' or '!' + // at beginning of the line. Make sure it points to start of the first word + // in the line. + if (isStartOfCommentLineCharFound) { + size_t firstWordPos = line.find_first_not_of(" \t", pos); + if (firstWordPos == string::npos) { + m_tokenList.push_back(Token(END_LINE, "\n")); + continue; + } + + if (firstWordPos > pos) { + m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, firstWordPos - pos))); + pos = firstWordPos; + } + } else { + m_tokenList.push_back(Token(PLAINSTRING, line.substr(0, pos))); + } + + while (pos != string::npos) { + // find the end of the word + size_t doxyCmdOrHtmlTagPos = line.find_first_of("\\@<>&\" \t", pos); + if (doxyCmdOrHtmlTagPos != pos) { + // plain text found + // if the last char is punctuation, make it a separate word, otherwise + // it may be included with word also when not appropriate, for example: + // colors are \b red, green, and blue --> colors are red, green, and blue + // instead of (comma not bold): + // colors are \b red, green, and blue --> colors are red, green, and blue + // In Python it looks even worse: + // colors are \b red, green, and blue --> colors are 'red,' green, and blue + string text = line.substr(pos, doxyCmdOrHtmlTagPos - pos); + string punctuations(".,:"); + size_t textSize = text.size(); + + if (!text.empty() + && punctuations.find(text[text.size() - 1]) != string::npos && + // but do not break ellipsis (...) + !(textSize > 1 && text[textSize - 2] == '.')) { + m_tokenList.push_back(Token(PLAINSTRING, text.substr(0, text.size() - 1))); + m_tokenList.push_back(Token(PLAINSTRING, text.substr(text.size() - 1))); + } else { + m_tokenList.push_back(Token(PLAINSTRING, text)); + } + } + + pos = doxyCmdOrHtmlTagPos; + if (pos != string::npos) { + if (m_isVerbatimText) { + pos = processVerbatimText(pos, line); + + } else if (m_isInQuotedString) { + + if (line[pos] == '"') { + m_isInQuotedString = false; + } + m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, 1))); + pos++; + + } else { + pos = processNormalComment(pos, line); + } + } + } + m_tokenList.push_back(Token(END_LINE, "\n")); // add when pos == npos - end of line + } + + m_tokenListIt = m_tokenList.begin(); +} + +void DoxygenParser::printList() { + + int tokNo = 0; + for (TokenListCIt it = m_tokenList.begin(); it != m_tokenList.end(); it++, tokNo++) { + + cout << it->toString() << " "; + + if ((tokNo % TOKENSPERLINE) == 0) { + cout << endl; + } + } +} + +void DoxygenParser::printListError(int warningType, const std::string &message) { + int curLine = m_fileLineNo; + for (TokenListCIt it = m_tokenList.begin(); it != m_tokenListIt; it++) { + if (it->m_tokenType == END_LINE) { + curLine++; + } + } + + Swig_warning(warningType, m_fileName.c_str(), curLine, "%s\n", message.c_str()); +} diff --git a/Source/Doxygen/doxyparser.h b/Source/Doxygen/doxyparser.h new file mode 100644 index 000000000..96c71d22f --- /dev/null +++ b/Source/Doxygen/doxyparser.h @@ -0,0 +1,372 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * doxyparser.h + * ----------------------------------------------------------------------------- */ + +#ifndef DOXYGENPARSER_H_ +#define DOXYGENPARSER_H_ +#include +#include +#include +#include +#include + +#include "swig.h" + +#include "doxyentity.h" + +class DoxygenParser { +private: + + enum DoxyCommandEnum { + NONE = -1, + SIMPLECOMMAND, + COMMANDWORD, + COMMANDLINE, + COMMANDPARAGRAPH, + COMMANDENDCOMMAND, + COMMANDWORDPARAGRAPH, + COMMANDWORDLINE, + COMMANDWORDOWORDWORD, + COMMANDOWORD, + COMMANDERRORTHROW, + COMMANDUNIQUE, + COMMAND_HTML, + COMMAND_HTML_ENTITY, + COMMAND_ALIAS, + COMMAND_IGNORE, + END_LINE, + PARAGRAPH_END, + PLAINSTRING, + COMMAND + }; + + + /** This class contains parts of Doxygen comment as a token. */ + class Token { + public: + DoxyCommandEnum m_tokenType; + std::string m_tokenString; /* the data , such as param for @param */ + + Token(DoxyCommandEnum tType, std::string tString) : m_tokenType(tType), m_tokenString(tString) { + } + + std::string toString() const { + switch (m_tokenType) { + case END_LINE: + return "{END OF LINE}"; + case PARAGRAPH_END: + return "{END OF PARAGRAPH}"; + case PLAINSTRING: + return "{PLAINSTRING :" + m_tokenString + "}"; + case COMMAND: + return "{COMMAND : " + m_tokenString + "}"; + default: + return ""; + } + } + }; + + + typedef std::vector TokenList; + typedef TokenList::const_iterator TokenListCIt; + typedef TokenList::iterator TokenListIt; + + TokenList m_tokenList; + TokenListCIt m_tokenListIt; + + typedef std::map DoxyCommandsMap; + typedef DoxyCommandsMap::iterator DoxyCommandsMapIt; + + /* + * Map of Doxygen commands to determine if a string is a + * command and how it needs to be parsed + */ + static DoxyCommandsMap doxygenCommands; + static std::set doxygenSectionIndicators; + + bool m_isVerbatimText; // used to handle \htmlonly and \verbatim commands + bool m_isInQuotedString; + + Node *m_node; + std::string m_fileName; + int m_fileLineNo; + + /* + * Return the end command for a command appearing in "ignore" feature or empty + * string if this is a simple command and not a block one. + */ + std::string getIgnoreFeatureEndCommand(const std::string &theCommand) const; + + /* + * Helper for getting the value of doxygen:ignore feature or its argument. + */ + String *getIgnoreFeature(const std::string &theCommand, const char *argument = NULL) const; + + /* + * Whether to print lots of debug info during parsing + */ + bool noisy; + + /* + *Changes a std::string to all lower case + */ + std::string stringToLower(const std::string &stringToConvert); + + /* + * isSectionIndicator returns a boolean if the command is a section indicator + * This is a helper method for finding the end of a paragraph + * by Doxygen's terms + */ + bool isSectionIndicator(const std::string &smallString); + /* + * Determines how a command should be handled (what group it belongs to + * for parsing rules + */ + DoxyCommandEnum commandBelongs(const std::string &theCommand); + + /* + *prints the parse tree + */ + void printTree(const std::list &rootList); + + /** + * Returns true if the next token is end of line token. This is important + * when single word commands like \c are at the end of line. + */ + bool isEndOfLine(); + + /** + * Skips spaces, tabs, and end of line tokens. + */ + void skipWhitespaceTokens(); + + /** + * Removes all spaces and tabs from beginning end end of string. + */ + std::string trim(const std::string &text); + + /* + * Returns string of the next token if the next token is PLAINSTRING. Returns + * empty string otherwise. + */ + std::string getNextToken(); + + /* + * Returns the next word ON THE CURRENT LINE ONLY + * if a new line is encountered, returns a blank std::string. + * Updates the iterator if successful. + */ + std::string getNextWord(); + + /* + * Returns the next word, which is not necessarily on the same line. + * Updates the iterator if successful. + */ + std::string getNextWordInComment(); + + /* + * Returns the location of the end of the line as + * an iterator. + */ + TokenListCIt getOneLine(const TokenList &tokList); + + /* + * Returns a properly formatted std::string + * up til ANY command or end of line is encountered. + */ + std::string getStringTilCommand(const TokenList &tokList); + + /* + * Returns a properly formatted std::string + * up til the command specified is encountered + */ + //TODO check that this behaves properly for formulas + std::string getStringTilEndCommand(const std::string &theCommand, const TokenList &tokList); + + /* + * Returns the end of a Paragraph as an iterator- + * Paragraph is defined in Doxygen to be a paragraph of text + * separated by either a structural command or a blank line + */ + TokenListCIt getEndOfParagraph(const TokenList &tokList); + + /* + * Returns the end of a section, defined as the first blank line OR first + * encounter of the same command. Example of this behaviour is \arg. + * If no end is encountered, returns the last token of the std::list. + */ + TokenListCIt getEndOfSection(const std::string &theCommand, const TokenList &tokList); + + /* + * This method is for returning the end of a specific form of doxygen command + * that begins with a \command and ends in \endcommand + * such as \code and \endcode. The proper usage is + * progressTilEndCommand("endcode", tokenList); + * If the end is never encountered, it returns the end of the std::list. + */ + TokenListCIt getEndCommand(const std::string &theCommand, const TokenList &tokList); + /* + * A special method for commands such as \arg that end at the end of a + * paragraph OR when another \arg is encountered + //TODO getTilAnyCommand + TokenListCIt getTilAnyCommand(const std::string &theCommand, const TokenList &tokList); + */ + + /** + * This methods skips end of line token, if it is the next token to be + * processed. It is called with comment commands which have args till the + * end of line, such as 'addtogroup' or 'addindex'. + * It is up to translator to specific language to decide whether + * to insert eol or not. For example, if a command is ignored in target + * language, new lines may make formatting ugly (Python). + */ + void skipEndOfLine(); + + /* + * Method for Adding a Simple Command + * Format: @command + * Plain commands, such as newline etc, they contain no other data + * \n \\ \@ \& \$ \# \< \> \% + */ + void addSimpleCommand(const std::string &theCommand, DoxygenEntityList &doxyList); + /* + * CommandWord + * Format: @command + * Commands with a single WORD after then such as @b + * "a", "b", "c", "e", "em", "p", "def", "enum", "example", "package", + * "relates", "namespace", "relatesalso","anchor", "dontinclude", "include", + * "includelineno" + */ + void addCommandWord(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + /* + * CommandLine + * Format: @command (line) + * Commands with a single LINE after then such as @var + * "addindex", "fn", "name", "line", "var", "skipline", "typedef", "skip", + * "until", "property" + */ + void addCommandLine(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + /* + * CommandParagraph + * Format: @command {paragraph} + * Commands with a single paragraph after then such as @return + * "return", "remarks", "since", "test", "sa", "see", "pre", "post", + * "details", "invariant", "deprecated", "date", "note", "warning", + * "version", "todo", "bug", "attention", "brief", "arg", "author" + */ + void addCommandParagraph(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + /* + * Command EndCommand + * Format: @command and ends at @endcommand + * Commands that take in a block of text such as @code: + * "code", "dot", "msc", "f$", "f[", "f{environment}{", "htmlonly", + * "latexonly", "manonly", "verbatim", "xmlonly", "cond", "if", "ifnot", + * "link" + * Returns 1 if success, 0 if the endcommand is never encountered. + */ + void addCommandEndCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + /* + * CommandWordParagraph + * Format: @command {paragraph} + * Commands such as param + * "param", "tparam", "throw", "throws", "retval", "exception" + */ + void addCommandWordParagraph(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + /* + * CommandWordLine + * Format: @command (line) + * Commands such as param + * "page", "subsection", "subsubsection", "section", "paragraph", "defgroup" + */ + void addCommandWordLine(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + /* + * Command Word Optional Word Optional Word + * Format: @command [] [] + * Commands such as class + * "category", "class", "protocol", "interface", "struct", "union" + */ + void addCommandWordOWordOWord(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + /* + * Command Optional Word + * Format: @command [] + * Commands such as dir + * "dir", "file", "cond" + */ + void addCommandOWord(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + + /* + * Commands that should not be encountered (such as PHP only) + * goes til the end of line then returns + */ + void addCommandErrorThrow(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + + void addCommandHtml(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + + void addCommandHtmlEntity(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + + /* + *Adds the unique commands- different process for each unique command + */ + void addCommandUnique(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + + /* + * Replace the given command with its predefined alias expansion. + */ + void aliasCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + + /* + * Simply ignore the given command, possibly with the word following it or + * until the matching end command. + */ + void ignoreCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList); + + /* + * The actual "meat" of the doxygen parser. Calls the correct addCommand...() + * function. + */ + void addCommand(const std::string &commandString, const TokenList &tokList, DoxygenEntityList &doxyList); + + DoxygenEntityList parse(TokenListCIt endParsingIndex, const TokenList &tokList, bool root = false); + + /* + * Fill static doxygenCommands and sectionIndicators containers + */ + void fillTables(); + + /** Processes comment when \htmlonly and \verbatim commands are encountered. */ + size_t processVerbatimText(size_t pos, const std::string &line); + + bool processEscapedChars(size_t &pos, const std::string &line); + void processWordCommands(size_t &pos, const std::string &line); + void processHtmlTags(size_t &pos, const std::string &line); + void processHtmlEntities(size_t &pos, const std::string &line); + + + /** Processes comment outside \htmlonly and \verbatim commands. */ + size_t processNormalComment(size_t pos, const std::string &line); + + void tokenizeDoxygenComment(const std::string &doxygenComment, const std::string &fileName, int fileLine); + void printList(); + void printListError(int warningType, const std::string &message); + + typedef std::vector StringVector; + typedef StringVector::const_iterator StringVectorCIt; + + StringVector split(const std::string &text, char separator); + bool isStartOfDoxyCommentChar(char c); + bool addDoxyCommand(DoxygenParser::TokenList &tokList, const std::string &cmd); + +public: + DoxygenParser(bool noisy = false); + virtual ~DoxygenParser(); + DoxygenEntityList createTree(Node *node, String *documentation); +}; + +#endif diff --git a/Source/Doxygen/doxytranslator.cxx b/Source/Doxygen/doxytranslator.cxx new file mode 100644 index 000000000..fb21de75c --- /dev/null +++ b/Source/Doxygen/doxytranslator.cxx @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * doxytranslator.cxx + * + * Module to return documentation for nodes formatted for various documentation + * systems. + * ----------------------------------------------------------------------------- */ + +#include "doxytranslator.h" + +DoxygenTranslator::DoxygenTranslator(int flags) : m_flags(flags), parser((flags &debug_parser) != 0) { +} + + +DoxygenTranslator::~DoxygenTranslator() { +} + + +bool DoxygenTranslator::hasDocumentation(Node *node) { + return getDoxygenComment(node) != NULL; +} + + +String *DoxygenTranslator::getDoxygenComment(Node *node) { + return Getattr(node, "doxygen"); +} + +/** + * Indent all lines in the comment by given indentation string + */ +void DoxygenTranslator::extraIndentation(String *comment, const_String_or_char_ptr indentationString) { + if (indentationString || Len(indentationString) > 0) { + int len = Len(comment); + bool trailing_newline = len > 0 && *(Char(comment) + len - 1) == '\n'; + Insert(comment, 0, indentationString); + String *replace = NewStringf("\n%s", indentationString); + Replaceall(comment, "\n", replace); + if (trailing_newline) { + len = Len(comment); + Delslice(comment, len - 2, len); // Remove added trailing spaces on last line + } + Delete(replace); + } +} + +String *DoxygenTranslator::getDocumentation(Node *node, const_String_or_char_ptr indentationString) { + + if (!hasDocumentation(node)) { + return NewString(""); + } + + String *documentation = makeDocumentation(node); + extraIndentation(documentation, indentationString); + return documentation; +} + + +void DoxygenTranslator::printTree(const DoxygenEntityList &entityList) { + + for (DoxygenEntityListCIt p = entityList.begin(); p != entityList.end(); p++) { + p->printEntity(0); + } +} diff --git a/Source/Doxygen/doxytranslator.h b/Source/Doxygen/doxytranslator.h new file mode 100644 index 000000000..f07b632a2 --- /dev/null +++ b/Source/Doxygen/doxytranslator.h @@ -0,0 +1,90 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * doxytranslator.h + * + * Module to return documentation for nodes formatted for various documentation + * systems. + * ----------------------------------------------------------------------------- */ + +#ifndef DOXYGENTRANSLATOR_H_ +#define DOXYGENTRANSLATOR_H_ + +#include "swig.h" +#include "doxyentity.h" +#include "doxyparser.h" +#include +#include + + +/* + * This is a base class for translator classes. It defines the basic interface + * for translators, which convert Doxygen comments into alternative formats for + * target languages. + */ +class DoxygenTranslator { +public: + /* + * Bit flags for the translator ctor. + * + * Derived classes may define additional flags. + */ + enum { + // Use DoxygenParser in "noisy" mode. + debug_parser = 1, + + // Output results of translating Doxygen comments. + debug_translator = 2 + }; + + /* + * Constructor + */ + DoxygenTranslator(int flags = 0); + + /* + * Virtual destructor. + */ + virtual ~DoxygenTranslator(); + + /* + * Return the documentation for a given node formated for the correct + * documentation system. + */ + String *getDocumentation(Node *node, const_String_or_char_ptr indentationString); + + /* + * Returns truem is the specified node has comment attached. + */ + bool hasDocumentation(Node *node); + + /* + * Get original comment string in Doxygen-format. + */ + String *getDoxygenComment(Node *node); + +protected: + // The flags passed to the ctor. + const int m_flags; + + DoxygenParser parser; + + /* + * Returns the documentation formatted for a target language. + */ + virtual String *makeDocumentation(Node *node) = 0; + + /* + * Prints the details of a parsed entity list to stdout (for debugging). + */ + void printTree(const DoxygenEntityList &entityList); + + void extraIndentation(String *comment, const_String_or_char_ptr indentationString); +}; + +#endif diff --git a/Source/Doxygen/javadoc.cxx b/Source/Doxygen/javadoc.cxx new file mode 100644 index 000000000..72f84ab6c --- /dev/null +++ b/Source/Doxygen/javadoc.cxx @@ -0,0 +1,845 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * javadoc.cxx + * ----------------------------------------------------------------------------- */ + +#include "javadoc.h" +#include "doxyparser.h" +#include +#include +#include +#include "swigmod.h" +#define APPROX_LINE_LENGTH 64 // characters per line allowed +#define TAB_SIZE 8 // current tab size in spaces +//TODO {@link} {@linkplain} {@docRoot}, and other useful doxy commands that are not a javadoc tag + +// define static tables, they are filled in JavaDocConverter's constructor +std::map > JavaDocConverter::tagHandlers; + +using std::string; +using std::list; +using std::vector; + +void JavaDocConverter::fillStaticTables() { + if (tagHandlers.size()) // fill only once + return; + + /* + * Some translation rules: + * + * @ and \ must be escaped for both Java and Python to appear on output: \@, \\, + * while Doxygen produces output in both cases. + * Rule: @ and \ with space on the right should get to output. + * + * :: remains intact, even in class::method(). But you can use class#method also + * in C++ comment and it is properly translated to C++ output (changed by doxygen to ::) + * and Java output (remains #). + * Rule: SWIG type system can't be used to convert C::m to C#m, because in Java it is C.m + * Use string replacement :: --> # in tag see and links. + * + * HTML tags must be translated - remain in Java, to markdown in Python + * + * Unknown HTML tags, for example is translated to <x> by doxygen, while + * Java src is and therefore invisible on output - browser ignores unknown command. + * This is handy in syntax descriptions, for example: more . + * + * Standalone < and > need not be translated, they are rendered properly in + * all three outputs. + * + * ., %, and " need not to be translated + * + * entities must be translated - remain in Java, something meaningful in Python (<, ...) + * + * - Python + * - add comments also to auto-generated methods like equals(), delete() in Java, + * and methods for std::vector(), ... + * Commenting methods of std types is simple - add comment to std_*.i file. + */ + + // these commands insert HTML tags + tagHandlers["a"] = make_pair(&JavaDocConverter::handleTagHtml, "i"); + tagHandlers["arg"] = make_pair(&JavaDocConverter::handleTagHtml, "li"); + tagHandlers["b"] = make_pair(&JavaDocConverter::handleTagHtml, "b"); + tagHandlers["c"] = make_pair(&JavaDocConverter::handleTagHtml, "code"); + tagHandlers["cite"] = make_pair(&JavaDocConverter::handleTagHtml, "i"); + tagHandlers["e"] = make_pair(&JavaDocConverter::handleTagHtml, "i"); + tagHandlers["em"] = make_pair(&JavaDocConverter::handleTagHtml, "i"); + tagHandlers["li"] = make_pair(&JavaDocConverter::handleTagHtml, "li"); + tagHandlers["p"] = make_pair(&JavaDocConverter::handleTagHtml, "code"); + // these commands insert just a single char, some of them need to be escaped + tagHandlers["$"] = make_pair(&JavaDocConverter::handleTagChar, ""); + tagHandlers["@"] = make_pair(&JavaDocConverter::handleTagChar, ""); + tagHandlers["\\"] = make_pair(&JavaDocConverter::handleTagChar, ""); + tagHandlers["<"] = make_pair(&JavaDocConverter::handleTagChar, "<"); + tagHandlers[">"] = make_pair(&JavaDocConverter::handleTagChar, ">"); + tagHandlers["&"] = make_pair(&JavaDocConverter::handleTagChar, "&"); + tagHandlers["#"] = make_pair(&JavaDocConverter::handleTagChar, ""); + tagHandlers["%"] = make_pair(&JavaDocConverter::handleTagChar, ""); + tagHandlers["~"] = make_pair(&JavaDocConverter::handleTagChar, ""); + tagHandlers["\""] = make_pair(&JavaDocConverter::handleTagChar, """); + tagHandlers["."] = make_pair(&JavaDocConverter::handleTagChar, ""); + tagHandlers["::"] = make_pair(&JavaDocConverter::handleTagChar, ""); + // these commands are stripped out + tagHandlers["attention"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["anchor"] = make_pair(&JavaDocConverter::handleTagAnchor, ""); + tagHandlers["brief"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["bug"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["date"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["details"] = make_pair(&JavaDocConverter::handleParagraph, ""); + // this command is inserts text accumulated after cmd htmlonly - + // see DoxygenParser - CMD_HTML_ONLY. + tagHandlers["htmlonly"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["invariant"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["latexonly"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["manonly"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["partofdescription"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["rtfonly"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["short"] = make_pair(&JavaDocConverter::handleParagraph, ""); + tagHandlers["xmlonly"] = make_pair(&JavaDocConverter::handleParagraph, ""); + // these commands are kept as-is, they are supported by JavaDoc + tagHandlers["author"] = make_pair(&JavaDocConverter::handleTagSame, ""); + tagHandlers["authors"] = make_pair(&JavaDocConverter::handleTagSame, "author"); + tagHandlers["deprecated"] = make_pair(&JavaDocConverter::handleTagSame, ""); + tagHandlers["exception"] = make_pair(&JavaDocConverter::handleTagSame, ""); + tagHandlers["package"] = make_pair(&JavaDocConverter::handleTagSame, ""); + tagHandlers["param"] = make_pair(&JavaDocConverter::handleTagParam, ""); + tagHandlers["tparam"] = make_pair(&JavaDocConverter::handleTagParam, ""); + tagHandlers["ref"] = make_pair(&JavaDocConverter::handleTagRef, ""); + tagHandlers["result"] = make_pair(&JavaDocConverter::handleTagSame, "return"); + tagHandlers["return"] = make_pair(&JavaDocConverter::handleTagSame, ""); + tagHandlers["returns"] = make_pair(&JavaDocConverter::handleTagSame, "return"); + //tagHandlers["see"] = make_pair(&JavaDocConverter::handleTagSame, ""); + //tagHandlers["sa"] = make_pair(&JavaDocConverter::handleTagSame, "see"); + tagHandlers["since"] = make_pair(&JavaDocConverter::handleTagSame, ""); + tagHandlers["throws"] = make_pair(&JavaDocConverter::handleTagSame, ""); + tagHandlers["throw"] = make_pair(&JavaDocConverter::handleTagSame, "throws"); + tagHandlers["version"] = make_pair(&JavaDocConverter::handleTagSame, ""); + // these commands have special handlers + tagHandlers["code"] = make_pair(&JavaDocConverter::handleTagExtended, "code"); + tagHandlers["cond"] = make_pair(&JavaDocConverter::handleTagMessage, "Conditional comment: "); + tagHandlers["copyright"] = make_pair(&JavaDocConverter::handleTagMessage, "Copyright: "); + tagHandlers["else"] = make_pair(&JavaDocConverter::handleTagIf, "Else: "); + tagHandlers["elseif"] = make_pair(&JavaDocConverter::handleTagIf, "Else if: "); + tagHandlers["endcond"] = make_pair(&JavaDocConverter::handleTagMessage, "End of conditional comment."); + // space in second arg prevents Javadoc to treat '@ example' as command. File name of + // example is still informative to user. + tagHandlers["example"] = make_pair(&JavaDocConverter::handleTagSame, " example"); + tagHandlers["if"] = make_pair(&JavaDocConverter::handleTagIf, "If: "); + tagHandlers["ifnot"] = make_pair(&JavaDocConverter::handleTagIf, "If not: "); + tagHandlers["image"] = make_pair(&JavaDocConverter::handleTagImage, ""); + tagHandlers["link"] = make_pair(&JavaDocConverter::handleTagLink, ""); + tagHandlers["see"] = make_pair(&JavaDocConverter::handleTagSee, ""); + tagHandlers["sa"] = make_pair(&JavaDocConverter::handleTagSee, ""); + tagHandlers["note"] = make_pair(&JavaDocConverter::handleTagMessage, "Note: "); + tagHandlers["overload"] = make_pair(&JavaDocConverter::handleTagMessage, + "This is an overloaded member function, provided for" + " convenience. It differs from the above function only in what" " argument(s) it accepts."); + tagHandlers["par"] = make_pair(&JavaDocConverter::handleTagPar, ""); + tagHandlers["remark"] = make_pair(&JavaDocConverter::handleTagMessage, "Remarks: "); + tagHandlers["remarks"] = make_pair(&JavaDocConverter::handleTagMessage, "Remarks: "); + tagHandlers["todo"] = make_pair(&JavaDocConverter::handleTagMessage, "TODO: "); + tagHandlers["verbatim"] = make_pair(&JavaDocConverter::handleTagExtended, "literal"); + + // \f commands output literal Latex formula, which is still better than nothing. + tagHandlers["f$"] = make_pair(&JavaDocConverter::handleTagVerbatim, ""); + tagHandlers["f["] = make_pair(&JavaDocConverter::handleTagVerbatim, ""); + tagHandlers["f{"] = make_pair(&JavaDocConverter::handleTagVerbatim, ""); + + tagHandlers["warning"] = make_pair(&JavaDocConverter::handleTagMessage, "Warning: "); + // this command just prints it's contents + // (it is internal command of swig's parser, contains plain text) + tagHandlers["plainstd::string"] = make_pair(&JavaDocConverter::handlePlainString, ""); + tagHandlers["plainstd::endl"] = make_pair(&JavaDocConverter::handleNewLine, ""); + tagHandlers["n"] = make_pair(&JavaDocConverter::handleNewLine, ""); + + // HTML tags + tagHandlers[" 0 && i + 1 < unformattedLine.length()) { + if (!isFirstLine) + for (int j = 0; j < indent; j++) { + formattedLines.append("\t"); + } else { + isFirstLine = 0; + } + formattedLines.append(unformattedLine.substr(lastPosition, i - lastPosition + 1)); + formattedLines.append("\n *"); + + } + } + if (lastPosition < unformattedLine.length()) { + if (!isFirstLine) { + for (int j = 0; j < indent; j++) { + formattedLines.append("\t"); + } + } + formattedLines.append(unformattedLine.substr(lastPosition, unformattedLine.length() - lastPosition)); + } + + return formattedLines; +} + +/** + * Returns true, if the given parameter exists in the current node + * (for example param is a name of function parameter). If feature + * 'doxygen:nostripparams' is set, then this method always returns + * true - parameters are copied to output regardless of presence in + * function params list. + */ +bool JavaDocConverter::paramExists(std::string param) { + + if (GetFlag(currentNode, "feature:doxygen:nostripparams")) { + return true; + } + + ParmList *plist = CopyParmList(Getattr(currentNode, "parms")); + + for (Parm *p = plist; p;) { + + if (Getattr(p, "name") && Char(Getattr(p, "name")) == param) { + return true; + } + /* doesn't seem to work always: in some cases (especially for 'self' parameters) + * tmap:in is present, but tmap:in:next is not and so this code skips all the parameters + */ + //p = Getattr(p, "tmap:in") ? Getattr(p, "tmap:in:next") : nextSibling(p); + p = nextSibling(p); + } + + Delete(plist); + + return false; +} + +std::string JavaDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) { + std::string translatedComment; + + if (doxygenEntity.isLeaf) { + return translatedComment; + } + + for (DoxygenEntityListIt p = doxygenEntity.entityList.begin(); p != doxygenEntity.entityList.end(); p++) { + + translateEntity(*p, translatedComment); + translateSubtree(*p); + } + + return translatedComment; +} + +/** + * Checks if a handler for the given tag exists, and calls it. + */ +void JavaDocConverter::translateEntity(DoxygenEntity &tag, std::string &translatedComment) { + + std::map >::iterator it; + it = tagHandlers.find(tag.typeOfEntity); + + if (it != tagHandlers.end()) { + (this->*(it->second.first))(tag, translatedComment, it->second.second); + } else { + // do NOT print warning, since there are many tags, which are not + // translatable - many warnings hide important ones + // addError(WARN_DOXYGEN_COMMAND_ERROR, "Unknown doxygen or HTML tag: " + tag.typeOfEntity); + } +} + + +void JavaDocConverter::handleTagAnchor(DoxygenEntity &tag, std::string &translatedComment, std::string &) { + translatedComment += ""; +} + + +void JavaDocConverter::handleTagHtml(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) { + if (tag.entityList.size()) { // do not include empty tags + std::string tagData = translateSubtree(tag); + // wrap the thing, ignoring whitespace + size_t wsPos = tagData.find_last_not_of("\n\t "); + if (wsPos != std::string::npos) + translatedComment += "<" + arg + ">" + tagData.substr(0, wsPos + 1) + "" + tagData.substr(wsPos + 1); + else + translatedComment += "<" + arg + ">" + translateSubtree(tag) + " "; + } +} + +void JavaDocConverter::handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) { + std::string htmlTagArgs = tag.data; + if (htmlTagArgs == "/") { + // end html tag, for example " + translatedComment += ""; + } else { + translatedComment += arg + htmlTagArgs + ">"; + } +} + +void JavaDocConverter::handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, std::string &arg) { + // html entities can be preserved for Java + translatedComment += arg + ';'; +} + +void JavaDocConverter::handleNewLine(DoxygenEntity &, std::string &translatedComment, std::string &) { + //
    tag is added, because otherwise to much text is joined + // into same paragraph by javadoc. For example, doxy list: + // - item one + // - item two + // becomes one paragraph with surrounding text without newlines. + // This way we get to many empty lines in javadoc output, but this + // is still better than joined lines. Possibility for improvements + // exists. + translatedComment += "
    \n * "; +} + +void JavaDocConverter::handleTagChar(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) { + // escape it if we need to, else just print + if (arg.size()) + translatedComment += arg; + else + translatedComment += tag.typeOfEntity; +} + +// handles tags which are the same in Doxygen and Javadoc. +void JavaDocConverter::handleTagSame(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) { + if (arg.size()) + tag.typeOfEntity = arg; + translatedComment += formatCommand(std::string("@" + tag.typeOfEntity + " " + translateSubtree(tag)), 2); +} + +void JavaDocConverter::handleParagraph(DoxygenEntity &tag, std::string &translatedComment, std::string &) { + translatedComment += formatCommand(translateSubtree(tag), 0); +} + +void JavaDocConverter::handlePlainString(DoxygenEntity &tag, std::string &translatedComment, std::string &) { + translatedComment += tag.data; + // if (tag.data.size() && tag.data[tag.data.size()-1] != ' ') + // translatedComment += " "; +} + +void JavaDocConverter::handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) { + translatedComment += arg + " "; + for (DoxygenEntityListCIt it = tag.entityList.begin(); it != tag.entityList.end(); it++) { + translatedComment += it->data; + } +} + +void JavaDocConverter::handleTagExtended(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) { + std::string dummy; + translatedComment += "{@" + arg + " "; + handleParagraph(tag, translatedComment, dummy); + translatedComment += "}"; +} + +void JavaDocConverter::handleTagIf(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) { + std::string dummy; + translatedComment += arg; + if (tag.entityList.size()) { + translatedComment += tag.entityList.begin()->data; + tag.entityList.pop_front(); + translatedComment += " {" + translateSubtree(tag) + "}"; + } +} + +void JavaDocConverter::handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) { + std::string dummy; + translatedComment += formatCommand(arg, 0); + handleParagraph(tag, translatedComment, dummy); +} + +void JavaDocConverter::handleTagImage(DoxygenEntity &tag, std::string &translatedComment, std::string &) { + if (tag.entityList.size() < 2) + return; + + std::string file; + std::string title; + + std::list::iterator it = tag.entityList.begin(); + if (it->data != "html") + return; + + it++; + file = it->data; + + it++; + if (it != tag.entityList.end()) + title = it->data; + + translatedComment += " + title;
+
+  // the size indication is supported for Latex only in Doxygen, see manual
+
+  translatedComment += "; +} + +void JavaDocConverter::handleTagPar(DoxygenEntity &tag, std::string &translatedComment, std::string &) { + std::string dummy; + translatedComment += "data + "\""; + translatedComment += ">"; + tag.entityList.pop_front(); + handleParagraph(tag, translatedComment, dummy); + } + translatedComment += "

    "; +} + + +void JavaDocConverter::handleTagParam(DoxygenEntity &tag, std::string &translatedComment, std::string &) { + std::string dummy; + + if (!tag.entityList.size()) + return; + if (!paramExists(tag.entityList.begin()->data)) + return; + + translatedComment += "@param "; + translatedComment += tag.entityList.begin()->data; + tag.entityList.pop_front(); + handleParagraph(tag, translatedComment, dummy); +} + + +void JavaDocConverter::handleTagRef(DoxygenEntity &tag, std::string &translatedComment, std::string &) { + std::string dummy; + if (!tag.entityList.size()) + return; + + // we translate to link, although \page is not supported in Java, but + // reader at least knows what to look at. Also for \anchor tag on the same + // page this link works. + string anchor = tag.entityList.begin()->data; + tag.entityList.pop_front(); + string anchorText = anchor; + if (!tag.entityList.empty()) { + anchorText = tag.entityList.begin()->data; + } + translatedComment += "" + anchorText + ""; +} + + +string JavaDocConverter::convertLink(string linkObject) { + if (GetFlag(currentNode, "feature:doxygen:nolinktranslate")) + return linkObject; + // find the params in function in linkObject (if any) + size_t lbracePos = linkObject.find('(', 0); + size_t rbracePos = linkObject.find(')', 0); + if (lbracePos == string::npos || rbracePos == string::npos || lbracePos >= rbracePos) + return ""; + + string paramsStr = linkObject.substr(lbracePos + 1, + rbracePos - lbracePos - 1); + // strip the params, to fill them later + string additionalObject = linkObject.substr(rbracePos + 1, string::npos); + linkObject = linkObject.substr(0, lbracePos); + + // find all the params + vector params; + size_t lastPos = 0, commaPos = 0; + while (true) { + commaPos = paramsStr.find(',', lastPos); + if (commaPos == string::npos) + commaPos = paramsStr.size(); + string param = paramsStr.substr(lastPos, commaPos - lastPos); + // if any param type is empty, we are failed + if (!param.size()) + return ""; + params.push_back(param); + lastPos = commaPos + 1; + if (lastPos >= paramsStr.size()) + break; + } + + linkObject += "("; + for (size_t i = 0; i < params.size(); i++) { + // translate c/c++ type string to swig's type + // i e 'int **arr[100][10]' -> 'a(100).a(10).p.p.int' + // also converting arrays to pointers + string paramStr = params[i]; + String *swigType = NewString(""); + + // handle const qualifier + if (paramStr.find("const") != string::npos) + SwigType_add_qualifier(swigType, "const"); + + // handle pointers, references and arrays + for (int j = (int)params[i].size() - 1; j >= 0; j--) { + // skip all the [...] blocks, write 'p.' for every of it + if (paramStr[j] == ']') { + while (j >= 0 && paramStr[j] != '[') + j--; + // no closing brace + if (j < 0) + return ""; + SwigType_add_pointer(swigType); + continue; + } else if (paramStr[j] == '*') + SwigType_add_pointer(swigType); + else if (paramStr[j] == '&') + SwigType_add_reference(swigType); + else if (isalnum(paramStr[j])) { + size_t typeNameStart = paramStr.find_last_of(' ', j + 1); + if (typeNameStart == string::npos) + typeNameStart = 0; + else + typeNameStart++; + Append(swigType, paramStr.substr(typeNameStart, j - typeNameStart + 1).c_str()); + break; + } + } + + // make dummy param list, to lookup typemaps for it + Parm *dummyParam = NewParm(swigType, "", 0); + Swig_typemap_attach_parms("jstype", dummyParam, NULL); + Language::instance()->replaceSpecialVariables(0, Getattr(dummyParam, "tmap:jstype"), dummyParam); + + //Swig_print(dummyParam, 1); + linkObject += Char(Getattr(dummyParam, "tmap:jstype")); + if (i != params.size() - 1) + linkObject += ","; + + Delete(dummyParam); + Delete(swigType); + } + linkObject += ")"; + + return linkObject + additionalObject; +} + +void JavaDocConverter::handleTagLink(DoxygenEntity &tag, std::string &translatedComment, std::string &) { + std::string dummy; + if (!tag.entityList.size()) + return; + + string linkObject = convertLink(tag.entityList.begin()->data); + if (!linkObject.size()) + linkObject = tag.entityList.begin()->data; + tag.entityList.pop_front(); + + translatedComment += "{@link "; + translatedComment += linkObject + " "; + handleParagraph(tag, translatedComment, dummy); + translatedComment += "}"; +} + +void JavaDocConverter::handleTagSee(DoxygenEntity &tag, std::string &translatedComment, std::string &) { + std::string dummy; + if (!tag.entityList.size()) + return; + + // tag.entity list contains contents of the @see paragraph. It should contain + // one link (references) to method with or without parameters. Doxygen supports + // arbitrary text and types mixed, but this feature is not supported here. + // :: or # may be used as a separator between class name and method name. + list::iterator it; + string methodRef; + for (it = tag.entityList.begin(); it != tag.entityList.end(); it++) { + if (it->typeOfEntity == "plainstd::endl") { + // handleNewLine(*it, translatedComment, dummy); + continue; + } + // restore entities which may be used in C++ type declaration + if (it->typeOfEntity == "&") { + methodRef += '&'; + } else if (it->typeOfEntity == "<") { + methodRef += '<'; + } else if (it->typeOfEntity == ">") { + methodRef += '>'; + } else { + methodRef += it->data; + } + } + + // replace :: with #, but only if it appears before left brace + size_t lbrace = methodRef.find('('); + size_t dblColon = methodRef.find("::"); + if (dblColon < lbrace) { + methodRef = methodRef.substr(0, dblColon) + '#' + methodRef.substr(dblColon + 2); + } + + translatedComment += "@see "; + string linkObject = convertLink(methodRef); + if (!linkObject.size()) { + linkObject = methodRef; + } + translatedComment += linkObject; +} + +/* This function moves all line endings at the end of child entities + * out of the child entities to the parent. + * For example, entity tree: + + -root + |-param + |-paramText + |-endline + + should be turned to + + -root + |-param + |-paramText + |-endline + * + */ +int JavaDocConverter::shiftEndlinesUpTree(DoxygenEntity &root, int level) { + DoxygenEntityListIt it = root.entityList.begin(); + while (it != root.entityList.end()) { + // remove line endings + int ret = shiftEndlinesUpTree(*it, level + 1); + // insert them after this element + it++; + for (int i = 0; i < ret; i++) { + root.entityList.insert(it, DoxygenEntity("plainstd::endl")); + } + } + + // continue only if we are not root + if (!level) { + return 0; + } + + int removedCount = 0; + while (!root.entityList.empty() + && root.entityList.rbegin()->typeOfEntity == "plainstd::endl") { + root.entityList.pop_back(); + removedCount++; + } + return removedCount; +} + +/** + * This makes sure that all comment lines contain '*'. It is not mandatory in doxygen, + * but highly recommended for Javadoc. '*' in empty lines are indented according + * to indentation of the first line. Indentation of non-empty lines is not + * changed - garbage in garbage out. + */ +std::string JavaDocConverter::indentAndInsertAsterisks(const string &doc) { + + size_t idx = doc.find('\n'); + size_t indent = 0; + bool singleLineComment = idx == string::npos; + // Detect indentation. + // The first line in comment is the one after '/**', which may be + // spaces and '\n' or the text. In any case it is not suitable to detect + // indentation, so we have to skip the first '\n'. + // However, if there is just one line, then use that line to detect indentation. + if (idx != string::npos) { + size_t nonspaceIdx = doc.find_first_not_of(" \t", idx + 1); + if (nonspaceIdx != string::npos) { + indent = nonspaceIdx - idx; + } + } + + if (indent == 0) { + // we can't indent the first line less than 0 + indent = 1; + } + // Create the first line of Javadoc comment. + string indentStr(indent - 1, ' '); + string translatedStr = indentStr + "/**"; + if (indent > 1) { + // remove the first space, so that '*' will be aligned + translatedStr = translatedStr.substr(1); + } + + translatedStr += doc; + + // insert '*' before each comment line, if it does not have it + idx = translatedStr.find('\n'); + + while (idx != string::npos) { + + size_t nonspaceIdx = translatedStr.find_first_not_of(" \t", idx + 1); + if (nonspaceIdx != string::npos && translatedStr[nonspaceIdx] != '*') { + // line without '*' found - is it empty? + if (translatedStr[nonspaceIdx] != '\n') { + // add '* ' to each line without it + translatedStr = translatedStr.substr(0, nonspaceIdx) + "* " + translatedStr.substr(nonspaceIdx); + //printf(translatedStr.c_str()); + } else { + // we found empty line, replace it with indented '*' + translatedStr = translatedStr.substr(0, idx + 1) + indentStr + "* " + translatedStr.substr(nonspaceIdx); + } + } + idx = translatedStr.find('\n', nonspaceIdx); + } + + // Add the last comment line properly indented + size_t nonspaceEndIdx = translatedStr.find_last_not_of(" \t"); + if (nonspaceEndIdx != string::npos) { + if (translatedStr[nonspaceEndIdx] != '\n') { + if (!singleLineComment) + translatedStr += '\n'; + } else { + // remove trailing spaces + translatedStr = translatedStr.substr(0, nonspaceEndIdx + 1); + } + } + translatedStr += indentStr + "*/\n"; + + return translatedStr; +} + +String *JavaDocConverter::makeDocumentation(Node *node) { + + String *documentation = getDoxygenComment(node); + + if (documentation == NULL) { + return NewString(""); + } + + if (GetFlag(node, "feature:doxygen:notranslate")) { + + string doc = Char(documentation); + + string translatedStr = indentAndInsertAsterisks(doc); + + return NewString(translatedStr.c_str()); + } + + DoxygenEntityList entityList = parser.createTree(node, documentation); + + // entityList.sort(CompareDoxygenEntities()); sorting currently not used, + + if (m_flags & debug_translator) { + std::cout << "---RESORTED LIST---" << std::endl; + printTree(entityList); + } + // store the current node + // (currently just to handle params) + currentNode = node; + + std::string javaDocString = "/**\n * "; + + DoxygenEntity root("root", entityList); + + shiftEndlinesUpTree(root); + + // strip line endings at the beginning + while (!root.entityList.empty() + && root.entityList.begin()->typeOfEntity == "plainstd::endl") { + root.entityList.pop_front(); + } + + // and at the end + while (!root.entityList.empty() + && root.entityList.rbegin()->typeOfEntity == "plainstd::endl") { + root.entityList.pop_back(); + } + + javaDocString += translateSubtree(root); + + javaDocString += "\n */\n"; + + if (m_flags & debug_translator) { + std::cout << "\n---RESULT IN JAVADOC---" << std::endl; + std::cout << javaDocString; + } + + return NewString(javaDocString.c_str()); +} + +void JavaDocConverter::addError(int warningType, const std::string &message) { + Swig_warning(warningType, "", 0, "Doxygen parser warning: %s. \n", message.c_str()); +} diff --git a/Source/Doxygen/javadoc.h b/Source/Doxygen/javadoc.h new file mode 100644 index 000000000..6feff5295 --- /dev/null +++ b/Source/Doxygen/javadoc.h @@ -0,0 +1,169 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * javadoc.h + * + * Module to return documentation for nodes formatted for JavaDoc + * ----------------------------------------------------------------------------- */ + +#ifndef JAVADOCCONVERTER_H_ +#define JAVADOCCONVERTER_H_ + +#include "doxytranslator.h" +#include + +/* + * A class to translate doxygen comments into JavaDoc style comments. + */ +class JavaDocConverter : public DoxygenTranslator { +public: + JavaDocConverter(int flags = 0); + String *makeDocumentation(Node *node); + +protected: + /* + * Used to properly format JavaDoc-style command + */ + std::string formatCommand(std::string unformattedLine, int indent); + + /* + * Translate every entity in a tree. + */ + std::string translateSubtree(DoxygenEntity &doxygenEntity); + + /* + * Translate one entity with the appropriate handler, according + * to the tagHandlers + */ + void translateEntity(DoxygenEntity &tag, std::string &translatedComment); + + /* + * Fix all endlines location, etc + */ + int shiftEndlinesUpTree(DoxygenEntity &root, int level = 0); + + /* + * Convert params in link-objects and references + */ + std::string convertLink(std::string linkObject); + + /* + * Typedef for the function that handles one tag + * arg - some string argument to easily pass it through lookup table + */ + typedef void (JavaDocConverter::*tagHandler) (DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /** + * Copies verbatim args of the tag to output, used for commands like \f$, ... + */ + void handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /** Creates anchor link. */ + void handleTagAnchor(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Wrap the command data with the html tag + * arg - html tag, with no braces + */ + void handleTagHtml(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* Handles HTML tags recognized by Doxygen, like ,
      , , ... */ + void handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* Handles HTML entities recognized by Doxygen, like <, ©, ... */ + void handleHtmlEntity(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Just prints new line + */ + void handleNewLine(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Print the name of tag to the output, used for escape-commands + * arg - html-escaped variant, if not provided the command data is used + */ + void handleTagChar(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Do not translate and print as-is + * arg - the new tag name, if it needs to be renamed + */ + void handleTagSame(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Print only the content and strip original tag + */ + void handleParagraph(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Print only data part of code + */ + void handlePlainString(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Print extended Javadoc command, like {@code ...} or {@literal ...} + * arg - command name + */ + void handleTagExtended(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Print the if-elseif-else-endif section + */ + void handleTagIf(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Prints the specified message, than the contents of the tag + * arg - message + */ + void handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Insert tag if the 'format' field is specified as 'html' + */ + void handleTagImage(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Insert

      ...

      + */ + void handleTagPar(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Insert \@param command, if it is really a function param + */ + void handleTagParam(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Writes link for \ref tag. + */ + void handleTagRef(DoxygenEntity &tag, std::string &translatedComment, std::string &); + + /* + * Insert {@link...} command, and handle all the s correctly + * (like converting types of params, etc) + */ + void handleTagLink(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + + /* + * Insert @see command, and handle all the s correctly + * (like converting types of params, etc) + */ + void handleTagSee(DoxygenEntity &tag, std::string &translatedComment, std::string &arg); + +private: + Node *currentNode; + // this contains the handler pointer and one string argument + static std::map > tagHandlers; + void fillStaticTables(); + + bool paramExists(std::string param); + std::string indentAndInsertAsterisks(const std::string &doc); + + void addError(int warningType, const std::string &message); +}; + +#endif diff --git a/Source/Doxygen/pydoc.cxx b/Source/Doxygen/pydoc.cxx new file mode 100644 index 000000000..eb489932a --- /dev/null +++ b/Source/Doxygen/pydoc.cxx @@ -0,0 +1,911 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * pydoc.cxx + * + * Module to return documentation for nodes formatted for PyDoc + * ----------------------------------------------------------------------------- */ + +#include "pydoc.h" +#include "doxyparser.h" +#include +#include +#include +#include + +#include "swigmod.h" + +// define static tables, they are filled in PyDocConverter's constructor +PyDocConverter::TagHandlersMap PyDocConverter::tagHandlers; +std::map PyDocConverter::sectionTitles; + +using std::string; + +// Helper class increasing the provided indent string in its ctor and decreasing +// it in its dtor. +class IndentGuard { +public: + // One indent level. + static const char *Level() { + return " "; + } + // Default ctor doesn't do anything and prevents the dtor from doing anything// too and should only be used when the guard needs to be initialized// conditionally as Init() can then be called after checking some condition.// Otherwise, prefer to use the non default ctor below. + IndentGuard() { + m_initialized = false; + } + + // Ctor takes the output to determine the current indent and to remove the + // extra indent added to it in the dtor and the variable containing the indent + // to use, which must be used after every new line by the code actually + // updating the output. + IndentGuard(string &output, string &indent) { + Init(output, indent); + } + + // Really initializes the object created using the default ctor. + void Init(string &output, string &indent) { + m_output = &output; + m_indent = &indent; + + const string::size_type lastNonSpace = m_output->find_last_not_of(' '); + if (lastNonSpace == string::npos) { + m_firstLineIndent = m_output->length(); + } else if ((*m_output)[lastNonSpace] == '\n') { + m_firstLineIndent = m_output->length() - (lastNonSpace + 1); + } else { + m_firstLineIndent = 0; + } + + // Notice that the indent doesn't include the first line indent because it's + // implicit, i.e. it is present in the input and so is copied into the + // output anyhow. + *m_indent = Level(); + + m_initialized = true; + } + + // Get the indent for the first line of the paragraph, which is smaller than + // the indent for the subsequent lines. + string getFirstLineIndent() const { + return string(m_firstLineIndent, ' '); + } + + ~IndentGuard() { + if (!m_initialized) + return; + + m_indent->clear(); + + // Get rid of possible remaining extra indent, e.g. if there were any trailing + // new lines: we shouldn't add the extra indent level to whatever follows + // this paragraph. + static const size_t lenIndentLevel = strlen(Level()); + if (m_output->length() > lenIndentLevel) { + const size_t start = m_output->length() - lenIndentLevel; + if (m_output->compare(start, string::npos, Level()) == 0) + m_output->erase(start); + } + } + +private: + string *m_output; + string *m_indent; + string::size_type m_firstLineIndent; + bool m_initialized; + + IndentGuard(const IndentGuard &); + IndentGuard &operator=(const IndentGuard &); +}; + +// Return the indent of the given multiline string, i.e. the maximal number of +// spaces present in the beginning of all its non-empty lines. +static size_t determineIndent(const string &s) { + size_t minIndent = static_cast(-1); + + for (size_t lineStart = 0; lineStart < s.length();) { + const size_t lineEnd = s.find('\n', lineStart); + const size_t firstNonSpace = s.find_first_not_of(' ', lineStart); + + // If inequality doesn't hold, it means that this line contains only spaces + // (notice that this works whether lineEnd is valid or string::npos), in + // which case it doesn't matter when determining the indent. + if (firstNonSpace < lineEnd) { + // Here we can be sure firstNonSpace != string::npos. + const size_t lineIndent = firstNonSpace - lineStart; + if (lineIndent < minIndent) + minIndent = lineIndent; + } + + if (lineEnd == string::npos) + break; + + lineStart = lineEnd + 1; + } + + return minIndent; +} + +static void trimWhitespace(string &s) { + const string::size_type lastNonSpace = s.find_last_not_of(' '); + if (lastNonSpace == string::npos) + s.clear(); + else + s.erase(lastNonSpace + 1); +} + +// Erase the first character in the string if it is a newline +static void eraseLeadingNewLine(string &s) { + if (!s.empty() && s[0] == '\n') + s.erase(s.begin()); +} + +// Erase the last character in the string if it is a newline +static void eraseTrailingNewLine(string &s) { + if (!s.empty() && s[s.size() - 1] == '\n') + s.erase(s.size() - 1); +} + +// Check the generated docstring line by line and make sure that any +// code and verbatim blocks have an empty line preceding them, which +// is necessary for Sphinx. Additionally, this strips any empty lines +// appearing at the beginning of the docstring. +static string padCodeAndVerbatimBlocks(const string &docString) { + std::string result; + + std::istringstream iss(docString); + + // Initialize to false because there is no previous line yet + bool lastLineWasNonBlank = false; + + for (string line; std::getline(iss, line); result += line) { + if (!result.empty()) { + // Terminate the previous line + result += '\n'; + } + + const size_t pos = line.find_first_not_of(" \t"); + if (pos == string::npos) { + lastLineWasNonBlank = false; + } else { + if (lastLineWasNonBlank && + (line.compare(pos, 13, ".. code-block") == 0 || + line.compare(pos, 7, ".. math") == 0)) { + // Must separate code or math blocks from the previous line + result += '\n'; + } + lastLineWasNonBlank = true; + } + } + return result; +} + +/* static */ +PyDocConverter::TagHandlersMap::mapped_type PyDocConverter::make_handler(tagHandler handler) { + return make_pair(handler, std::string()); +} + +/* static */ +PyDocConverter::TagHandlersMap::mapped_type PyDocConverter::make_handler(tagHandler handler, const char *arg) { + return make_pair(handler, arg); +} + +void PyDocConverter::fillStaticTables() { + if (tagHandlers.size()) // fill only once + return; + + // table of section titles, they are printed only once + // for each group of specified doxygen commands + sectionTitles["author"] = "Author: "; + sectionTitles["authors"] = "Authors: "; + sectionTitles["copyright"] = "Copyright: "; + sectionTitles["deprecated"] = "Deprecated: "; + sectionTitles["example"] = "Example: "; + sectionTitles["note"] = "Notes: "; + sectionTitles["remark"] = "Remarks: "; + sectionTitles["remarks"] = "Remarks: "; + sectionTitles["warning"] = "Warning: "; +// sectionTitles["sa"] = "See also: "; +// sectionTitles["see"] = "See also: "; + sectionTitles["since"] = "Since: "; + sectionTitles["todo"] = "TODO: "; + sectionTitles["version"] = "Version: "; + + tagHandlers["a"] = make_handler(&PyDocConverter::handleTagWrap, "*"); + tagHandlers["b"] = make_handler(&PyDocConverter::handleTagWrap, "**"); + // \c command is translated as single quotes around next word + tagHandlers["c"] = make_handler(&PyDocConverter::handleTagWrap, "``"); + tagHandlers["cite"] = make_handler(&PyDocConverter::handleTagWrap, "'"); + tagHandlers["e"] = make_handler(&PyDocConverter::handleTagWrap, "*"); + // these commands insert just a single char, some of them need to be escaped + tagHandlers["$"] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers["@"] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers["\\"] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers["<"] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers[">"] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers["&"] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers["#"] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers["%"] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers["~"] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers["\""] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers["."] = make_handler(&PyDocConverter::handleTagChar); + tagHandlers["::"] = make_handler(&PyDocConverter::handleTagChar); + // these commands are stripped out, and only their content is printed + tagHandlers["attention"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["author"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["authors"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["brief"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["bug"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["code"] = make_handler(&PyDocConverter::handleCode); + tagHandlers["copyright"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["date"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["deprecated"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["details"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["em"] = make_handler(&PyDocConverter::handleParagraph, " "); + tagHandlers["example"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["exception"] = tagHandlers["throw"] = tagHandlers["throws"] = make_handler(&PyDocConverter::handleTagException); + tagHandlers["htmlonly"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["invariant"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["latexonly"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["link"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["manonly"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["note"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["p"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["partofdescription"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["rtfonly"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["remark"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["remarks"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["sa"] = make_handler(&PyDocConverter::handleTagMessage, "See also: "); + tagHandlers["see"] = make_handler(&PyDocConverter::handleTagMessage, "See also: "); + tagHandlers["since"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["short"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["todo"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["version"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["verbatim"] = make_handler(&PyDocConverter::handleVerbatimBlock); + tagHandlers["warning"] = make_handler(&PyDocConverter::handleParagraph); + tagHandlers["xmlonly"] = make_handler(&PyDocConverter::handleParagraph); + // these commands have special handlers + tagHandlers["arg"] = make_handler(&PyDocConverter::handleTagMessage, "* "); + tagHandlers["cond"] = make_handler(&PyDocConverter::handleTagMessage, "Conditional comment: "); + tagHandlers["else"] = make_handler(&PyDocConverter::handleTagIf, "Else: "); + tagHandlers["elseif"] = make_handler(&PyDocConverter::handleTagIf, "Else if: "); + tagHandlers["endcond"] = make_handler(&PyDocConverter::handleTagMessage, "End of conditional comment."); + tagHandlers["if"] = make_handler(&PyDocConverter::handleTagIf, "If: "); + tagHandlers["ifnot"] = make_handler(&PyDocConverter::handleTagIf, "If not: "); + tagHandlers["image"] = make_handler(&PyDocConverter::handleTagImage); + tagHandlers["li"] = make_handler(&PyDocConverter::handleTagMessage, "* "); + tagHandlers["overload"] = make_handler(&PyDocConverter::handleTagMessage, + "This is an overloaded member function, provided for" + " convenience.\nIt differs from the above function only in what" " argument(s) it accepts."); + tagHandlers["par"] = make_handler(&PyDocConverter::handleTagPar); + tagHandlers["param"] = tagHandlers["tparam"] = make_handler(&PyDocConverter::handleTagParam); + tagHandlers["ref"] = make_handler(&PyDocConverter::handleTagRef); + tagHandlers["result"] = tagHandlers["return"] = tagHandlers["returns"] = make_handler(&PyDocConverter::handleTagReturn); + + // this command just prints it's contents + // (it is internal command of swig's parser, contains plain text) + tagHandlers["plainstd::string"] = make_handler(&PyDocConverter::handlePlainString); + tagHandlers["plainstd::endl"] = make_handler(&PyDocConverter::handleNewLine); + tagHandlers["n"] = make_handler(&PyDocConverter::handleNewLine); + + // \f commands output literal Latex formula, which is still better than nothing. + tagHandlers["f$"] = tagHandlers["f["] = tagHandlers["f{"] = make_handler(&PyDocConverter::handleMath); + + // HTML tags + tagHandlers[""); + tagHandlers["&"] = make_handler(&PyDocConverter::handleHtmlEntity, "&"); + tagHandlers["&apos"] = make_handler(&PyDocConverter::handleHtmlEntity, "'"); + tagHandlers["""] = make_handler(&PyDocConverter::handleHtmlEntity, "\""); + tagHandlers["&lsquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "`"); + tagHandlers["&rsquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "'"); + tagHandlers["&ldquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "\""); + tagHandlers["&rdquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "\""); + tagHandlers["&ndash"] = make_handler(&PyDocConverter::handleHtmlEntity, "-"); + tagHandlers["&mdash"] = make_handler(&PyDocConverter::handleHtmlEntity, "--"); + tagHandlers[" "] = make_handler(&PyDocConverter::handleHtmlEntity, " "); + tagHandlers["×"] = make_handler(&PyDocConverter::handleHtmlEntity, "x"); + tagHandlers["&minus"] = make_handler(&PyDocConverter::handleHtmlEntity, "-"); + tagHandlers["&sdot"] = make_handler(&PyDocConverter::handleHtmlEntity, "."); + tagHandlers["&sim"] = make_handler(&PyDocConverter::handleHtmlEntity, "~"); + tagHandlers["&le"] = make_handler(&PyDocConverter::handleHtmlEntity, "<="); + tagHandlers["&ge"] = make_handler(&PyDocConverter::handleHtmlEntity, ">="); + tagHandlers["&larr"] = make_handler(&PyDocConverter::handleHtmlEntity, "<--"); + tagHandlers["&rarr"] = make_handler(&PyDocConverter::handleHtmlEntity, "-->"); +} + +PyDocConverter::PyDocConverter(int flags): +DoxygenTranslator(flags), m_tableLineLen(0), m_prevRowIsTH(false) { + fillStaticTables(); +} + +// Return the type as it should appear in the output documentation. +static std::string getPyDocType(Node *n, const_String_or_char_ptr lname = "") { + std::string type; + + String *s = Swig_typemap_lookup("doctype", n, lname, 0); + if (!s) { + if (String *t = Getattr(n, "type")) + s = SwigType_str(t, ""); + } + + if (!s) + return type; + + if (Language::classLookup(s)) { + // In Python C++ namespaces are flattened, so remove all but last component + // of the name. + String *const last = Swig_scopename_last(s); + + // We are not actually sure whether it's a documented class or not, but + // there doesn't seem to be any harm in making it a reference if it isn't, + // while there is a lot of benefit in having a hyperlink if it is. + type = ":py:class:`"; + type += Char(last); + type += "`"; + + Delete(last); + } else { + type = Char(s); + } + + Delete(s); + + return type; +} + +std::string PyDocConverter::getParamType(std::string param) { + std::string type; + + ParmList *plist = CopyParmList(Getattr(currentNode, "parms")); + for (Parm *p = plist; p; p = nextSibling(p)) { + String *pname = Getattr(p, "name"); + if (Char(pname) != param) + continue; + + type = getPyDocType(p, pname); + break; + } + Delete(plist); + return type; +} + +std::string PyDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) { + std::string translatedComment; + + if (doxygenEntity.isLeaf) + return translatedComment; + + std::string currentSection; + std::list::iterator p = doxygenEntity.entityList.begin(); + while (p != doxygenEntity.entityList.end()) { + std::map::iterator it; + it = sectionTitles.find(p->typeOfEntity); + if (it != sectionTitles.end()) { + if (it->second != currentSection) { + currentSection = it->second; + translatedComment += currentSection; + } + } + translateEntity(*p, translatedComment); + translateSubtree(*p); + p++; + } + + return translatedComment; +} + +void PyDocConverter::translateEntity(DoxygenEntity &doxyEntity, std::string &translatedComment) { + // check if we have needed handler and call it + std::map >::iterator it; + it = tagHandlers.find(doxyEntity.typeOfEntity); + if (it != tagHandlers.end()) + (this->*(it->second.first)) (doxyEntity, translatedComment, it->second.second); +} + +void PyDocConverter::handleParagraph(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + translatedComment += translateSubtree(tag); +} + +void PyDocConverter::handleVerbatimBlock(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + string verb = translateSubtree(tag); + + eraseLeadingNewLine(verb); + + // Remove the last newline to prevent doubling the newline already present after \endverbatim + trimWhitespace(verb); // Needed to catch trailing newline below + eraseTrailingNewLine(verb); + translatedComment += verb; +} + +void PyDocConverter::handleMath(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) { + IndentGuard indent; + + // Only \f$ is translated to inline formulae, \f[ and \f{ are for the block ones. + const bool inlineFormula = tag.typeOfEntity == "f$"; + + string formulaNL; + + if (inlineFormula) { + translatedComment += ":math:`"; + } else { + indent.Init(translatedComment, m_indent); + + trimWhitespace(translatedComment); + + const string formulaIndent = indent.getFirstLineIndent(); + translatedComment += formulaIndent; + translatedComment += ".. math::\n"; + + formulaNL = '\n'; + formulaNL += formulaIndent; + formulaNL += m_indent; + translatedComment += formulaNL; + } + + std::string formula; + handleTagVerbatim(tag, formula, arg); + + // It is important to ensure that we have no spaces around the inline math + // contents, so strip them. + const size_t start = formula.find_first_not_of(" \t\n"); + const size_t end = formula.find_last_not_of(" \t\n"); + if (start != std::string::npos) { + for (size_t n = start; n <= end; n++) { + if (formula[n] == '\n') { + // New lines must be suppressed in inline maths and indented in the block ones. + if (!inlineFormula) + translatedComment += formulaNL; + } else { + // Just copy everything else. + translatedComment += formula[n]; + } + } + } + + if (inlineFormula) { + translatedComment += "`"; + } +} + +void PyDocConverter::handleCode(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) { + IndentGuard indent(translatedComment, m_indent); + + trimWhitespace(translatedComment); + + // Use the current indent for the code-block line itself. + translatedComment += indent.getFirstLineIndent(); + + // Go out on a limb and assume that examples in the C or C++ sources use C++. + // In the worst case, we'll highlight C code using C++ syntax which is not a + // big deal (TODO: handle Doxygen code command language argument). + translatedComment += ".. code-block:: c++\n\n"; + + // Specify the level of extra indentation that will be used for + // subsequent lines within the code block. Note that the correct + // "starting indentation" is already present in the input, so we + // only need to add the desired code block indentation. + string codeIndent = m_indent; + + std::string code; + handleTagVerbatim(tag, code, arg); + + // Try and remove leading newline, which is present for block \code + // command: + eraseLeadingNewLine(code); + + translatedComment += codeIndent; + for (size_t n = 0; n < code.length(); n++) { + if (code[n] == '\n') { + // Don't leave trailing white space, this results in PEP8 validation + // errors in Python code (which are performed by our own unit tests). + trimWhitespace(translatedComment); + translatedComment += '\n'; + + // Ensure that we indent all the lines by the code indent. + translatedComment += codeIndent; + } else { + // Just copy everything else. + translatedComment += code[n]; + } + } + + trimWhitespace(translatedComment); + + // For block commands, the translator adds the newline after + // \endcode, so try and compensate by removing the last newline from + // the code text: + eraseTrailingNewLine(translatedComment); +} + +void PyDocConverter::handlePlainString(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + translatedComment += tag.data; +} + +void PyDocConverter::handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) { + translatedComment += arg; + for (DoxygenEntityListCIt it = tag.entityList.begin(); it != tag.entityList.end(); it++) { + translatedComment += it->data; + } +} + +void PyDocConverter::handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) { + translatedComment += arg; + handleParagraph(tag, translatedComment); +} + +void PyDocConverter::handleTagChar(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + translatedComment += tag.typeOfEntity; +} + +void PyDocConverter::handleTagIf(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) { + translatedComment += arg; + if (tag.entityList.size()) { + translatedComment += tag.entityList.begin()->data; + tag.entityList.pop_front(); + translatedComment += " {" + translateSubtree(tag) + "}"; + } +} + +void PyDocConverter::handleTagPar(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + translatedComment += "Title: "; + if (tag.entityList.size()) + translatedComment += tag.entityList.begin()->data; + tag.entityList.pop_front(); + handleParagraph(tag, translatedComment); +} + +void PyDocConverter::handleTagImage(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + if (tag.entityList.size() < 2) + return; + tag.entityList.pop_front(); + translatedComment += "Image: "; + translatedComment += tag.entityList.begin()->data; + tag.entityList.pop_front(); + if (tag.entityList.size()) + translatedComment += "(" + tag.entityList.begin()->data + ")"; +} + +void PyDocConverter::handleTagParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + if (tag.entityList.size() < 2) + return; + + IndentGuard indent(translatedComment, m_indent); + + DoxygenEntity paramNameEntity = *tag.entityList.begin(); + tag.entityList.pop_front(); + + const std::string ¶mName = paramNameEntity.data; + + const std::string paramType = getParamType(paramName); + if (!paramType.empty()) { + translatedComment += ":type " + paramName + ": " + paramType + "\n"; + translatedComment += indent.getFirstLineIndent(); + } + + translatedComment += ":param " + paramName + ":"; + + handleParagraph(tag, translatedComment); +} + + +void PyDocConverter::handleTagReturn(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + IndentGuard indent(translatedComment, m_indent); + + const std::string pytype = getPyDocType(currentNode); + if (!pytype.empty()) { + translatedComment += ":rtype: "; + translatedComment += pytype; + translatedComment += "\n"; + translatedComment += indent.getFirstLineIndent(); + } + + translatedComment += ":return: "; + handleParagraph(tag, translatedComment); +} + + +void PyDocConverter::handleTagException(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + IndentGuard indent(translatedComment, m_indent); + + translatedComment += ":raises: "; + handleParagraph(tag, translatedComment); +} + + +void PyDocConverter::handleTagRef(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + if (!tag.entityList.size()) + return; + + string anchor = tag.entityList.begin()->data; + tag.entityList.pop_front(); + string anchorText = anchor; + if (!tag.entityList.empty()) { + anchorText = tag.entityList.begin()->data; + } + translatedComment += "'" + anchorText + "'"; +} + + +void PyDocConverter::handleTagWrap(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) { + if (tag.entityList.size()) { // do not include empty tags + std::string tagData = translateSubtree(tag); + // wrap the thing, ignoring whitespace + size_t wsPos = tagData.find_last_not_of("\n\t "); + if (wsPos != std::string::npos && wsPos != tagData.size() - 1) + translatedComment += arg + tagData.substr(0, wsPos + 1) + arg + tagData.substr(wsPos + 1); + else + translatedComment += arg + tagData + arg; + } +} + +void PyDocConverter::handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) { + std::string htmlTagArgs = tag.data; + if (htmlTagArgs == "/") { + // end html tag, for example " + // translatedComment += ""; + } else { + translatedComment += arg + htmlTagArgs; + } +} + +void PyDocConverter::handleDoxyHtmlTagNoParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) { + std::string htmlTagArgs = tag.data; + if (htmlTagArgs == "/") { + // end html tag, for example " + } else { + translatedComment += arg; + } +} + +void PyDocConverter::handleDoxyHtmlTag_A(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) { + std::string htmlTagArgs = tag.data; + if (htmlTagArgs == "/") { + // end html tag, " + translatedComment += " (" + m_url + ')'; + m_url.clear(); + } else { + m_url.clear(); + size_t pos = htmlTagArgs.find('='); + if (pos != string::npos) { + m_url = htmlTagArgs.substr(pos + 1); + } + translatedComment += arg; + } +} + +void PyDocConverter::handleDoxyHtmlTag2(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) { + std::string htmlTagArgs = tag.data; + if (htmlTagArgs == "/") { + // end html tag, for example " + translatedComment += arg; + } else { + translatedComment += arg; + } +} + +void PyDocConverter::handleDoxyHtmlTag_tr(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + std::string htmlTagArgs = tag.data; + size_t nlPos = translatedComment.rfind('\n'); + if (htmlTagArgs == "/") { + // end tag, appends vertical table line '|' + translatedComment += '|'; + if (nlPos != string::npos) { + size_t startOfTableLinePos = translatedComment.find_first_not_of(" \t", nlPos + 1); + if (startOfTableLinePos != string::npos) { + m_tableLineLen = translatedComment.size() - startOfTableLinePos; + } + } + } else { + if (m_prevRowIsTH) { + // if previous row contained is ignored + } else { + translatedComment += '|'; + m_prevRowIsTH = true; + } +} + +void PyDocConverter::handleDoxyHtmlTag_td(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + std::string htmlTagArgs = tag.data; + if (htmlTagArgs == "/") { + // end tag, is ignored + } else { + translatedComment += '|'; + } +} + +void PyDocConverter::handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, const std::string &arg) { + // html entities + translatedComment += arg; +} + +void PyDocConverter::handleNewLine(DoxygenEntity &, std::string &translatedComment, const std::string &) { + trimWhitespace(translatedComment); + + translatedComment += "\n"; + if (!m_indent.empty()) + translatedComment += m_indent; +} + +String *PyDocConverter::makeDocumentation(Node *n) { + String *documentation; + std::string pyDocString; + + // store the node, we may need it later + currentNode = n; + + // for overloaded functions we must concat documentation for underlying overloads + if (Getattr(n, "sym:overloaded")) { + // rewind to the first overload + while (Getattr(n, "sym:previousSibling")) + n = Getattr(n, "sym:previousSibling"); + + std::vector allDocumentation; + + // minimal indent of any documentation comments, not initialized yet + size_t minIndent = static_cast(-1); + + // for each real method (not a generated overload) append the documentation + string oneDoc; + while (n) { + documentation = getDoxygenComment(n); + if (!Swig_is_generated_overload(n) && documentation) { + currentNode = n; + if (GetFlag(n, "feature:doxygen:notranslate")) { + String *comment = NewString(""); + Append(comment, documentation); + Replaceall(comment, "\n *", "\n"); + oneDoc = Char(comment); + Delete(comment); + } else { + std::list entityList = parser.createTree(n, documentation); + DoxygenEntity root("root", entityList); + + oneDoc = translateSubtree(root); + } + + // find the minimal indent of this documentation comment, we need to + // ensure that the entire comment is indented by it to avoid the leading + // parts of the other lines being simply discarded later + const size_t oneIndent = determineIndent(oneDoc); + if (oneIndent < minIndent) + minIndent = oneIndent; + + allDocumentation.push_back(oneDoc); + } + n = Getattr(n, "sym:nextSibling"); + } + + // construct final documentation string + if (allDocumentation.size() > 1) { + string indentStr; + if (minIndent != static_cast(-1)) + indentStr.assign(minIndent, ' '); + + std::ostringstream concatDocString; + for (size_t realOverloadCount = 0; realOverloadCount < allDocumentation.size(); realOverloadCount++) { + if (realOverloadCount != 0) { + // separate it from the preceding one. + concatDocString << "\n" << indentStr << "|\n\n"; + } + + oneDoc = allDocumentation[realOverloadCount]; + trimWhitespace(oneDoc); + concatDocString << indentStr << "*Overload " << (realOverloadCount + 1) << ":*\n" << oneDoc; + } + pyDocString = concatDocString.str(); + } else if (allDocumentation.size() == 1) { + pyDocString = *(allDocumentation.begin()); + } + } + // for other nodes just process as normal + else { + documentation = getDoxygenComment(n); + if (documentation != NULL) { + if (GetFlag(n, "feature:doxygen:notranslate")) { + String *comment = NewString(""); + Append(comment, documentation); + Replaceall(comment, "\n *", "\n"); + pyDocString = Char(comment); + Delete(comment); + } else { + std::list entityList = parser.createTree(n, documentation); + DoxygenEntity root("root", entityList); + pyDocString = translateSubtree(root); + } + } + } + + // if we got something log the result + if (!pyDocString.empty()) { + + // remove the last '\n' since additional one is added during writing to file + eraseTrailingNewLine(pyDocString); + + // ensure that a blank line occurs before code or math blocks + pyDocString = padCodeAndVerbatimBlocks(pyDocString); + + if (m_flags & debug_translator) { + std::cout << "\n---RESULT IN PYDOC---" << std::endl; + std::cout << pyDocString; + std::cout << std::endl; + } + } + + return NewString(pyDocString.c_str()); +} diff --git a/Source/Doxygen/pydoc.h b/Source/Doxygen/pydoc.h new file mode 100644 index 000000000..df8997d76 --- /dev/null +++ b/Source/Doxygen/pydoc.h @@ -0,0 +1,203 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * pydoc.h + * + * Module to return documentation for nodes formatted for PyDoc + * ----------------------------------------------------------------------------- */ + +#ifndef PYDOCCONVERTER_H_ +#define PYDOCCONVERTER_H_ + +#include +#include +#include "swig.h" +#include "doxyentity.h" +#include "doxytranslator.h" + +#define DOC_STRING_LENGTH 64 // characters per line allowed +#define DOC_PARAM_STRING_LENGTH 30 // characters reserved for param name / type + +class PyDocConverter : public DoxygenTranslator { +public: + PyDocConverter(int flags = 0); + String *makeDocumentation(Node *node); + +protected: + + size_t m_tableLineLen; + bool m_prevRowIsTH; + std::string m_url; + + /* + * Translate every entity in a tree, also manages sections + * display. Prints title for every group of tags that have + * a section title associated with them + */ + std::string translateSubtree(DoxygenEntity &doxygenEntity); + + /* + * Translate one entity with the appropriate handler, according + * to the tagHandlers + */ + void translateEntity(DoxygenEntity &doxyEntity, std::string &translatedComment); + + /* + * Typedef for the function that handles one tag + * arg - some string argument to easily pass it through lookup table + */ + typedef void (PyDocConverter::*tagHandler) (DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Wrap the command data with the some string + * arg - string to wrap with, like '_' or '*' + */ + void handleTagWrap(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Just prints new line + */ + void handleNewLine(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Print the name of tag to the output, used for escape-commands + */ + void handleTagChar(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Format the contents of the \exception tag or its synonyms. + */ + void handleTagException(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Print only the content and strip original tag + */ + void handleParagraph(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string()); + + /* + * Handle Doxygen verbatim tag + */ + void handleVerbatimBlock(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string()); + + /* + * Handle one of the Doxygen formula-related tags. + */ + void handleMath(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Handle a code snippet. + */ + void handleCode(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Print only data part of code + */ + void handlePlainString(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /** + * Copies verbatim args of the tag to output, used for commands like \f$, ... + */ + void handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Print the if-elseif-else-endif section + */ + void handleTagIf(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Prints the specified message, than the contents of the tag + * arg - message + */ + void handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Insert 'Title: ...' + */ + void handleTagPar(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Insert 'Image: ...' + */ + void handleTagImage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Format nice param description with type information + */ + void handleTagParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Format the contents of the \return tag or its synonyms. + */ + void handleTagReturn(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Writes text for \ref tag. + */ + void handleTagRef(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* Handles HTML tags recognized by Doxygen, like ,
        ,
      tag, add horizontal separator + // but first get leading spaces, because they'll be needed for the next row + size_t numLeadingSpaces = translatedComment.size() - nlPos - 1; + + translatedComment += string(m_tableLineLen, '-') + '\n'; + + if (nlPos != string::npos) { + translatedComment += string(numLeadingSpaces, ' '); + } + m_prevRowIsTH = false; + } + } +} + +void PyDocConverter::handleDoxyHtmlTag_th(DoxygenEntity &tag, std::string &translatedComment, const std::string &) { + std::string htmlTagArgs = tag.data; + if (htmlTagArgs == "/") { + // end tag,
      , ... */ + + void handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /** Does not output params of HTML tag, for example in
      + * 'border=1' is not written to output. + */ + void handleDoxyHtmlTagNoParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /** Translates tag text to: text ("url"). */ + void handleDoxyHtmlTag_A(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* + * Handles HTML tags, which are translated to markdown-like syntax, for example + * text --> _text_. Appends arg for start HTML tag and end HTML tag. + */ + void handleDoxyHtmlTag2(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* Handles HTML table, tag */ + void handleDoxyHtmlTag_tr(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* Handles HTML table, tag
      */ + void handleDoxyHtmlTag_th(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* Handles HTML table, tag */ + void handleDoxyHtmlTag_td(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg); + + /* Handles HTML entities recognized by Doxygen, like <, ©, ... */ + void handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, const std::string &arg); + + + /* + * Simple helper function that calculates correct parameter type + * of the node stored in 'currentNode' + * If param with specified name is not found, empty string is returned + */ + std::string getParamType(std::string name); + +private: + // temporary thing, should be refactored somehow + Node *currentNode; + + // Extra indent for the current paragraph, must be output after each new line. + std::string m_indent; + + + // this contains the handler pointer and one string argument + typedef std::map >TagHandlersMap; + static TagHandlersMap tagHandlers; + + // this contains the sections tittles, like 'Arguments:' or 'Notes:', that are printed only once + static std::map sectionTitles; + + // Helper functions for fillStaticTables(): make a new tag handler object. + TagHandlersMap::mapped_type make_handler(tagHandler handler); + TagHandlersMap::mapped_type make_handler(tagHandler handler, const char *arg); + + void fillStaticTables(); +}; + +#endif diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index 7e5c454ff..da6c05b80 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -18,6 +18,8 @@ * Even though symbolic constants are used in the SWIG source, this is * not always the case in SWIG interface files. Do not change the * numbers in this file. + * + * This file is used as the input for generating Lib/swigwarn.swg. * ----------------------------------------------------------------------------- */ #ifndef SWIGWARN_H_ @@ -93,8 +95,8 @@ #define WARN_PARSE_EXTEND_NAME 326 #define WARN_CPP11_LAMBDA 340 -#define WARN_CPP11_ALIAS_DECLARATION 341 -#define WARN_CPP11_ALIAS_TEMPLATE 342 +#define WARN_CPP11_ALIAS_DECLARATION 341 /* redundant now */ +#define WARN_CPP11_ALIAS_TEMPLATE 342 /* redundant now */ #define WARN_CPP11_VARIADIC_TEMPLATE 343 #define WARN_IGNORE_OPERATOR_NEW 350 /* new */ @@ -153,6 +155,7 @@ #define WARN_TYPE_INCOMPLETE 402 #define WARN_TYPE_ABSTRACT 403 #define WARN_TYPE_REDEFINED 404 +#define WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405 #define WARN_TYPEMAP_SOURCETARGET 450 #define WARN_TYPEMAP_CHARLEAK 451 @@ -207,6 +210,18 @@ #define WARN_LANG_ILLEGAL_DESTRUCTOR 521 #define WARN_LANG_EXTEND_CONSTRUCTOR 522 #define WARN_LANG_EXTEND_DESTRUCTOR 523 +#define WARN_LANG_EXPERIMENTAL 524 +#define WARN_LANG_DIRECTOR_FINAL 525 + +/* -- Doxygen comments -- */ + +#define WARN_DOXYGEN_UNKNOWN_COMMAND 560 +#define WARN_DOXYGEN_UNEXPECTED_END_OF_COMMENT 561 +#define WARN_DOXYGEN_COMMAND_EXPECTED 562 +#define WARN_DOXYGEN_HTML_ERROR 563 +#define WARN_DOXYGEN_COMMAND_ERROR 564 +#define WARN_DOXYGEN_UNKNOWN_CHARACTER 565 +#define WARN_DOXYGEN_UNEXPECTED_ITERATOR_VALUE 566 /* -- Reserved (600-799) -- */ @@ -215,9 +230,9 @@ /* Feel free to claim any number in this space that's not currently being used. Just make sure you add an entry here */ -#define WARN_D_TYPEMAP_CTYPE_UNDEF 700 +#define WARN_D_TYPEMAP_CTYPE_UNDEF 700 #define WARN_D_TYPEMAP_IMTYPE_UNDEF 701 -#define WARN_D_TYPEMAP_DTYPE_UNDEF 702 +#define WARN_D_TYPEMAP_DTYPE_UNDEF 702 #define WARN_D_MULTIPLE_INHERITANCE 703 #define WARN_D_TYPEMAP_CLASSMOD_UNDEF 704 #define WARN_D_TYPEMAP_DBODY_UNDEF 705 diff --git a/Source/Makefile.am b/Source/Makefile.am index 0bb61b9ae..b67deb3d3 100644 --- a/Source/Makefile.am +++ b/Source/Makefile.am @@ -13,6 +13,7 @@ AM_CPPFLAGS = -I$(BUILD_SOURCE_DIR)/Include \ -I$(SOURCE_DIR)/Include \ -I$(SOURCE_DIR)/DOH \ -I$(SOURCE_DIR)/CParse \ + -I$(SOURCE_DIR)/Doxygen \ -I$(SOURCE_DIR)/Preprocessor \ -I$(SOURCE_DIR)/Swig \ -I$(SOURCE_DIR)/Modules @@ -34,12 +35,18 @@ eswig_SOURCES = CParse/cscanner.c \ DOH/memory.c \ DOH/string.c \ DOH/void.c \ - Modules/allegrocl.cxx \ + Doxygen/doxyentity.cxx \ + Doxygen/doxyentity.h \ + Doxygen/doxyparser.cxx \ + Doxygen/doxyparser.h \ + Doxygen/doxytranslator.cxx \ + Doxygen/doxytranslator.h \ + Doxygen/javadoc.cxx \ + Doxygen/javadoc.h \ + Doxygen/pydoc.cxx \ + Doxygen/pydoc.h \ Modules/allocate.cxx \ Modules/browser.cxx \ - Modules/cffi.cxx \ - Modules/chicken.cxx \ - Modules/clisp.cxx \ Modules/contract.cxx \ Modules/c.cxx \ Modules/csharp.cxx \ @@ -54,25 +61,20 @@ eswig_SOURCES = CParse/cscanner.c \ Modules/lang.cxx \ Modules/lua.cxx \ Modules/main.cxx \ - Modules/modula3.cxx \ - Modules/module.cxx \ Modules/mzscheme.cxx \ - Modules/nested.cxx \ + Modules/nested.cxx \ Modules/ocaml.cxx \ Modules/octave.cxx \ Modules/overload.cxx \ Modules/perl5.cxx \ Modules/php.cxx \ - Modules/pike.cxx \ Modules/python.cxx \ Modules/r.cxx \ Modules/ruby.cxx \ - Modules/s-exp.cxx \ Modules/scilab.cxx \ Modules/swigmain.cxx \ Modules/tcl8.cxx \ Modules/typepass.cxx \ - Modules/uffi.cxx \ Modules/utils.cxx \ Modules/xml.cxx \ Preprocessor/cpp.c \ @@ -91,8 +93,8 @@ eswig_SOURCES = CParse/cscanner.c \ Swig/stype.c \ Swig/symbol.c \ Swig/tree.c \ - Swig/typeobj.c \ Swig/typemap.c \ + Swig/typeobj.c \ Swig/typesys.c \ Swig/wrapfunc.c @@ -122,7 +124,7 @@ distclean-local: # swig executable as a way of checking before and after the 'beautifying'. # Single files can be beautified with the beautify-file target, eg: 'make beautify-file INDENTFILE=chosenfile.c' -SWIGTYPEDEFS=-T bool -T File -T DohObjInfo -T Parm -T Language -T List -T Typetab -T ModuleFactory -T ErrorMessageFormat -T Symtab -T Hash -T Scanner -T String -T DohBase -T Node -T String_or_char -T SwigType -T Dispatcher -T Wrapper -T DohStringMethods -T DohFileMethods -T DohListMethods -T DohHashMethods -T DOH -T DohIterator -T ParmList -T FILE -T HashNode -T DOHObj_or_char -T DOHFile -T DOHString -T DOHString_or_char -T UpcallData +SWIGTYPEDEFS=-T bool -T File -T DohObjInfo -T Parm -T Language -T List -T TargetLanguageModule -T Typetab -T ModuleFactory -T ErrorMessageFormat -T Symtab -T Hash -T Scanner -T String -T DohBase -T Node -T String_or_char -T SwigType -T Dispatcher -T Wrapper -T DohStringMethods -T DohFileMethods -T DohListMethods -T DohHashMethods -T DOH -T DohIterator -T ParmList -T FILE -T HashNode -T DOHObj_or_char -T DOHFile -T DOHString -T DOHString_or_char -T UpcallData INDENTBAKSDIR=../IndentBaks beautify: diff --git a/Source/Modules/allegrocl.cxx b/Source/Modules/allegrocl.cxx index b69e1dd70..97af186fe 100644 --- a/Source/Modules/allegrocl.cxx +++ b/Source/Modules/allegrocl.cxx @@ -471,7 +471,7 @@ void add_defined_foreign_type(Node *n, int overwrite = 0, String *k = 0, // a synonym type was found (held in variable 'match') // Printf(stderr, "setting primary synonym of %p to %p\n", new_node, match); if (new_node == match) - Printf(stderr, "Hey-4 * - '%s' is a synonym of iteself!\n", Getattr(new_node, "name")); + Printf(stderr, "Hey-4 * - '%s' is a synonym of itself!\n", Getattr(new_node, "name")); Setattr(new_node, "allegrocl:synonym-of", match); // Printf(stderr,"*** 4\n"); add_linked_type(new_node); @@ -1685,285 +1685,6 @@ int ALLEGROCL::top(Node *n) { return SWIG_OK; } -/* very shamelessly 'borrowed' from overload.cxx, which - keeps the below Swig_overload_rank() code to itself. - We don't need a dispatch function in the C++ wrapper - code; we want it over on the lisp side. */ - -#define Swig_overload_rank Allegrocl_swig_overload_rank - -#define MAX_OVERLOAD 256 - -/* Overload "argc" and "argv" */ -// String *argv_template_string; -// String *argc_template_string; - -struct Overloaded { - Node *n; /* Node */ - int argc; /* Argument count */ - ParmList *parms; /* Parameters used for overload check */ - int error; /* Ambiguity error */ -}; - -/* ----------------------------------------------------------------------------- - * Swig_overload_rank() - * - * This function takes an overloaded declaration and creates a list that ranks - * all overloaded methods in an order that can be used to generate a dispatch - * function. - * Slight difference in the way this function is used by scripting languages and - * statically typed languages. The script languages call this method via - * Swig_overload_dispatch() - where wrappers for all overloaded methods are generated, - * however sometimes the code can never be executed. The non-scripting languages - * call this method via Swig_overload_check() for each overloaded method in order - * to determine whether or not the method should be wrapped. Note the slight - * difference when overloading methods that differ by const only. The - * scripting languages will ignore the const method, whereas the non-scripting - * languages ignore the first method parsed. - * ----------------------------------------------------------------------------- */ - -static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { - Overloaded nodes[MAX_OVERLOAD]; - int nnodes = 0; - Node *o = Getattr(n, "sym:overloaded"); - Node *c; - - if (!o) - return 0; - - c = o; - while (c) { - if (Getattr(c, "error")) { - c = Getattr(c, "sym:nextSibling"); - continue; - } - /* if (SmartPointer && Getattr(c,"cplus:staticbase")) { - c = Getattr(c,"sym:nextSibling"); - continue; - } */ - - /* Make a list of all the declarations (methods) that are overloaded with - * this one particular method name */ - if (Getattr(c, "wrap:name")) { - nodes[nnodes].n = c; - nodes[nnodes].parms = Getattr(c, "wrap:parms"); - nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms); - nodes[nnodes].error = 0; - nnodes++; - } - c = Getattr(c, "sym:nextSibling"); - } - - /* Sort the declarations by required argument count */ - { - int i, j; - for (i = 0; i < nnodes; i++) { - for (j = i + 1; j < nnodes; j++) { - if (nodes[i].argc > nodes[j].argc) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - } - } - } - - /* Sort the declarations by argument types */ - { - int i, j; - for (i = 0; i < nnodes - 1; i++) { - if (nodes[i].argc == nodes[i + 1].argc) { - for (j = i + 1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) { - Parm *p1 = nodes[i].parms; - Parm *p2 = nodes[j].parms; - int differ = 0; - int num_checked = 0; - while (p1 && p2 && (num_checked < nodes[i].argc)) { - // Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type")); - if (checkAttribute(p1, "tmap:in:numinputs", "0")) { - p1 = Getattr(p1, "tmap:in:next"); - continue; - } - if (checkAttribute(p2, "tmap:in:numinputs", "0")) { - p2 = Getattr(p2, "tmap:in:next"); - continue; - } - String *t1 = Getattr(p1, "tmap:typecheck:precedence"); - String *t2 = Getattr(p2, "tmap:typecheck:precedence"); - if ((!t1) && (!nodes[i].error)) { - Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n), - "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n", - Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0)); - nodes[i].error = 1; - } else if ((!t2) && (!nodes[j].error)) { - Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n", - Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0)); - nodes[j].error = 1; - } - if (t1 && t2) { - int t1v, t2v; - t1v = atoi(Char(t1)); - t2v = atoi(Char(t2)); - differ = t1v - t2v; - } else if (!t1 && t2) - differ = 1; - else if (t1 && !t2) - differ = -1; - else if (!t1 && !t2) - differ = -1; - num_checked++; - if (differ > 0) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - break; - } else if ((differ == 0) && (Strcmp(t1, "0") == 0)) { - t1 = Getattr(p1, "ltype"); - if (!t1) { - t1 = SwigType_ltype(Getattr(p1, "type")); - if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) { - SwigType_add_pointer(t1); - } - Setattr(p1, "ltype", t1); - } - t2 = Getattr(p2, "ltype"); - if (!t2) { - t2 = SwigType_ltype(Getattr(p2, "type")); - if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) { - SwigType_add_pointer(t2); - } - Setattr(p2, "ltype", t2); - } - - /* Need subtype check here. If t2 is a subtype of t1, then we need to change the - order */ - - if (SwigType_issubtype(t2, t1)) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - - if (Strcmp(t1, t2) != 0) { - differ = 1; - break; - } - } else if (differ) { - break; - } - if (Getattr(p1, "tmap:in:next")) { - p1 = Getattr(p1, "tmap:in:next"); - } else { - p1 = nextSibling(p1); - } - if (Getattr(p2, "tmap:in:next")) { - p2 = Getattr(p2, "tmap:in:next"); - } else { - p2 = nextSibling(p2); - } - } - if (!differ) { - /* See if declarations differ by const only */ - String *d1 = Getattr(nodes[i].n, "decl"); - String *d2 = Getattr(nodes[j].n, "decl"); - if (d1 && d2) { - String *dq1 = Copy(d1); - String *dq2 = Copy(d2); - if (SwigType_isconst(d1)) { - Delete(SwigType_pop(dq1)); - } - if (SwigType_isconst(d2)) { - Delete(SwigType_pop(dq2)); - } - if (Strcmp(dq1, dq2) == 0) { - - if (SwigType_isconst(d1) && !SwigType_isconst(d2)) { - if (script_lang_wrapping) { - // Swap nodes so that the const method gets ignored (shadowed by the non-const method) - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - differ = 1; - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), - "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) { - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), - "using %s instead.\n", Swig_name_decl(nodes[i].n)); - } - } - } - nodes[j].error = 1; - } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) { - differ = 1; - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), - "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) { - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), - "using %s instead.\n", Swig_name_decl(nodes[i].n)); - } - } - } - nodes[j].error = 1; - } - } - Delete(dq1); - Delete(dq2); - } - } - if (!differ) { - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n), - "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) { - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), - "using %s instead.\n", Swig_name_decl(nodes[i].n)); - } - } - nodes[j].error = 1; - } - } - } - } - } - } - List *result = NewList(); - { - int i; - for (i = 0; i < nnodes; i++) { - if (nodes[i].error) - Setattr(nodes[i].n, "overload:ignore", "1"); - Append(result, nodes[i].n); - // Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms)); - // Swig_print_node(nodes[i].n); - } - } - return result; -} - -/* end shameless borrowing */ - int any_varargs(ParmList *pl) { Parm *p; @@ -2722,6 +2443,13 @@ int ALLEGROCL::functionWrapper(Node *n) { } } + /* See if there is any return cleanup code */ + if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) { + Replaceall(tm, "$source", Swig_cresult_name()); + Printf(f->code, "%s\n", tm); + Delete(tm); + } + emit_return_variable(n, t, f); if (CPlusPlus) { diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx index 3d382b378..23683c385 100644 --- a/Source/Modules/allocate.cxx +++ b/Source/Modules/allocate.cxx @@ -197,15 +197,17 @@ class Allocate:public Dispatcher { // Found a polymorphic method. // Mark the polymorphic method, in case the virtual keyword was not used. Setattr(n, "storage", "virtual"); - - if (both_have_public_access || both_have_protected_access) { - if (!is_non_public_base(inclass, b)) - Setattr(n, "override", base); // Note C# definition of override, ie access must be the same - } else if (!both_have_private_access) { - // Different access - if (this_wrapping_protected_members || base_wrapping_protected_members) + if (!Getattr(b, "feature:interface")) { // interface implementation neither hides nor overrides + if (both_have_public_access || both_have_protected_access) { if (!is_non_public_base(inclass, b)) - Setattr(n, "hides", base); // Note C# definition of hiding, ie hidden if access is different + Setattr(n, "override", base); // Note C# definition of override, ie access must be the same + } + else if (!both_have_private_access) { + // Different access + if (this_wrapping_protected_members || base_wrapping_protected_members) + if (!is_non_public_base(inclass, b)) + Setattr(n, "hides", base); // Note C# definition of hiding, ie hidden if access is different + } } // Try and find the most base's covariant return type SwigType *most_base_covariant_type = Getattr(base, "covariant"); @@ -502,7 +504,7 @@ class Allocate:public Dispatcher { in emit.cxx - and is either constructued from the "feature:catches" feature + and is either constructed from the "feature:catches" feature or copied from the node "throws" list. */ String *scatchlist = Getattr(n, "feature:catches"); diff --git a/Source/Modules/cffi.cxx b/Source/Modules/cffi.cxx index c355e452a..bf3338813 100644 --- a/Source/Modules/cffi.cxx +++ b/Source/Modules/cffi.cxx @@ -543,6 +543,14 @@ int CFFI::functionWrapper(Node *n) { cleanupFunction(n, f, parms); + /* See if there is any return cleanup code */ + String *tm = 0; + if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) { + Replaceall(tm, "$source", Swig_cresult_name()); + Printf(f->code, "%s\n", tm); + Delete(tm); + } + if (!is_void_return) { Printf(f->code, " return lresult;\n"); } diff --git a/Source/Modules/chicken.cxx b/Source/Modules/chicken.cxx index 68a42a29b..76b6455e2 100644 --- a/Source/Modules/chicken.cxx +++ b/Source/Modules/chicken.cxx @@ -547,7 +547,7 @@ int CHICKEN::functionWrapper(Node *n) { } emit_return_variable(n, d, f); - /* Insert the argumetn output code */ + /* Insert the argument output code */ Printv(f->code, argout, NIL); /* Output cleanup code */ @@ -1456,7 +1456,7 @@ String *CHICKEN::chickenPrimitiveName(String *name) { if (value) return value; else { - Swig_error(input_file, line_number, "Internal Error: attempting to reference non-existant primitive name %s\n", name); + Swig_error(input_file, line_number, "Internal Error: attempting to reference non-existent primitive name %s\n", name); return NewString("#f"); } } diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 01fd5435b..76ec6a4fb 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -68,8 +68,8 @@ class CSHARP:public Language { String *module_baseclass; //inheritance for module class from %pragma String *imclass_interfaces; //interfaces for intermediary class class from %pragma String *module_interfaces; //interfaces for module class from %pragma - String *imclass_class_modifiers; //class modifiers for intermediary class overriden by %pragma - String *module_class_modifiers; //class modifiers for module class overriden by %pragma + String *imclass_class_modifiers; //class modifiers for intermediary class overridden by %pragma + String *module_class_modifiers; //class modifiers for module class overridden by %pragma String *upcasts_code; //C++ casts for inheritance hierarchies C++ code String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code String *director_callback_typedefs; // Director function pointer typedefs for callbacks @@ -683,7 +683,7 @@ public: String *filen = NewStringf("%s%s.cs", dir, name); File *f = NewFile(filen, "w", SWIG_output_files()); if (!f) { - FileErrorDisplay(f); + FileErrorDisplay(filen); SWIG_exit(EXIT_FAILURE); } Append(filenames_list, Copy(filen)); @@ -1384,7 +1384,7 @@ public: // Wrap C/C++ enums with constant integers or use the typesafe enum pattern SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum "); Setattr(n, "type", typemap_lookup_type); - const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF); + const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF); String *return_type = Copy(tm); substituteClassname(typemap_lookup_type, return_type); @@ -1584,11 +1584,23 @@ public: * ----------------------------------------------------------------------------- */ virtual int insertDirective(Node *n) { + int ret = SWIG_OK; String *code = Getattr(n, "code"); + String *section = Getattr(n, "section"); Replaceall(code, "$module", module_class_name); Replaceall(code, "$imclassname", imclass_name); Replaceall(code, "$dllimport", dllimport); - return Language::insertDirective(n); + + if (!ImportMode && (Cmp(section, "proxycode") == 0)) { + if (proxy_class_code) { + Swig_typemap_replace_embedded_typemap(code, n); + int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0; + Printv(proxy_class_code, Char(code) + offset, "\n", NIL); + } + } else { + ret = Language::insertDirective(n); + } + return ret; } /* ----------------------------------------------------------------------------- @@ -1720,7 +1732,7 @@ public: Replaceall(cptr_method_name, ".", "_"); Replaceall(cptr_method_name, "$interfacename", interface_name); - String *upcast_method_name = Swig_name_member(getNSpace(), proxy_class_name, cptr_method_name); + String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name); upcastsCode(smart, upcast_method_name, c_classname, c_baseclass); Delete(upcast_method_name); @@ -1861,46 +1873,70 @@ public: typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class NIL); - // C++ destructor is wrapped by the Dispose method - // Note that the method name is specified in a typemap attribute called methodname + // C++ destructor is wrapped by the Finalize and Dispose methods + + const char *tmap_method = derived ? "csdestruct_derived" : "csdestruct"; + const String *tm = typemapExists(n, tmap_method, typemap_lookup_type); + if (tm) { + Swig_error(Getfile(tm), Getline(tm), + "A deprecated %s typemap was found for %s, please remove it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.\n", + tmap_method, proxy_class_name); + } + tmap_method = "csfinalize"; + tm = typemapExists(n, tmap_method, typemap_lookup_type); + if (tm) { + Swig_error(Getfile(tm), Getline(tm), + "A deprecated %s typemap was found for %s, please remove it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.\n", + tmap_method, proxy_class_name); + } + + tmap_method = derived ? "csdisposing_derived" : "csdisposing"; String *destruct = NewString(""); - const String *tm = NULL; attributes = NewHash(); - String *destruct_methodname = NULL; - String *destruct_methodmodifiers = NULL; + const String *destruct_methodname = NULL; + const String *destruct_methodmodifiers = NULL; + const String *destruct_parameters = NULL; if (derived) { - tm = typemapLookup(n, "csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes); - destruct_methodname = Getattr(attributes, "tmap:csdestruct_derived:methodname"); - destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct_derived:methodmodifiers"); + tm = typemapLookup(n, "csdisposing_derived", typemap_lookup_type, WARN_NONE, attributes); + destruct_methodname = Getattr(attributes, "tmap:csdisposing_derived:methodname"); + destruct_methodmodifiers = Getattr(attributes, "tmap:csdisposing_derived:methodmodifiers"); + destruct_parameters = Getattr(attributes, "tmap:csdisposing_derived:parameters"); } else { - tm = typemapLookup(n, "csdestruct", typemap_lookup_type, WARN_NONE, attributes); - destruct_methodname = Getattr(attributes, "tmap:csdestruct:methodname"); - destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct:methodmodifiers"); + tm = typemapLookup(n, "csdisposing", typemap_lookup_type, WARN_NONE, attributes); + destruct_methodname = Getattr(attributes, "tmap:csdisposing:methodname"); + destruct_methodmodifiers = Getattr(attributes, "tmap:csdisposing:methodmodifiers"); + destruct_parameters = Getattr(attributes, "tmap:csdisposing:parameters"); } if (tm && *Char(tm)) { if (!destruct_methodname) { - Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name); + Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in %s typemap for %s\n", tmap_method, proxy_class_name); } if (!destruct_methodmodifiers) { Swig_error(Getfile(n), Getline(n), - "No methodmodifiers attribute defined in csdestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name); + "No methodmodifiers attribute defined in %s typemap for %s.\n", tmap_method, proxy_class_name); } + if (!destruct_parameters) + destruct_parameters = empty_string; } // Emit the Finalize and Dispose methods if (tm) { - // Finalize method - if (*Char(destructor_call)) { - Printv(proxy_class_def, typemapLookup(n, "csfinalize", typemap_lookup_type, WARN_NONE), NIL); - } - // Dispose method + // Finalize and Dispose methods + Printv(proxy_class_def, typemapLookup(n, derived ? "csdispose_derived" : "csdispose", typemap_lookup_type, WARN_NONE), NIL); + // Dispose(bool disposing) method Printv(destruct, tm, NIL); if (*Char(destructor_call)) Replaceall(destruct, "$imcall", destructor_call); else Replaceall(destruct, "$imcall", "throw new global::System.MethodAccessException(\"C++ destructor does not have public access\")"); - if (*Char(destruct)) - Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n", - NIL); + if (*Char(destruct)) { + Printv(proxy_class_def, "\n ", NIL); + const String *methodmods = Getattr(n, "destructmethodmodifiers"); + if (methodmods) + Printv(proxy_class_def, methodmods, NIL); + else + Printv(proxy_class_def, destruct_methodmodifiers, " ", derived ? "override" : "virtual", NIL); + Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ") ", destruct, "\n", NIL); + } } if (*Char(interface_upcasts)) Printv(proxy_class_def, interface_upcasts, NIL); @@ -1917,7 +1953,7 @@ public: String *methid = Getattr(udata, "class_methodidx"); String *overname = Getattr(udata, "overname"); Printf(proxy_class_code, " if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s))\n", method, methid); - Printf(proxy_class_code, " swigDelegate%s = new SwigDelegate%s_%s(SwigDirector%s);\n", methid, proxy_class_name, methid, overname); + Printf(proxy_class_code, " swigDelegate%s = new SwigDelegate%s_%s(SwigDirectorMethod%s);\n", methid, proxy_class_name, methid, overname); } String *director_connect_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect"); Printf(proxy_class_code, " %s.%s(swigCPtr", imclass_name, director_connect_method_name); @@ -2044,34 +2080,6 @@ public: } } - /* ---------------------------------------------------------------------- - * calculateDirectBase() - * ---------------------------------------------------------------------- */ - - void calculateDirectBase(Node* n) { - Node* direct_base = 0; - // C++ inheritance - Node *attributes = NewHash(); - SwigType *typemap_lookup_type = Getattr(n, "classtypeobj"); - const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes); - bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false; - bool purebase_notderived = GetFlag(attributes, "tmap:csbase:notderived") ? true : false; - Delete(attributes); - if (!purebase_replace) { - if (List *baselist = Getattr(n, "bases")) { - Iterator base = First(baselist); - while (base.item && (GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface"))) - base = Next(base); - direct_base = base.item; - } - if (!direct_base && purebase_notderived) - direct_base = symbolLookup(const_cast(pure_baseclass)); - } else { - direct_base = symbolLookup(const_cast(pure_baseclass)); - } - Setattr(n, "direct_base", direct_base); - } - /* ---------------------------------------------------------------------- * classHandler() * ---------------------------------------------------------------------- */ @@ -2157,7 +2165,6 @@ public: emitInterfaceDeclaration(n, interface_name, interface_class_code); Delete(output_directory); } - calculateDirectBase(n); } Language::classHandler(n); @@ -2224,37 +2231,6 @@ public: --nesting_depth; } - /* Output the downcast method, if necessary. Note: There's no other really - good place to put this code, since Abstract Base Classes (ABCs) can and should have - downcasts, making the constructorHandler() a bad place (because ABCs don't get to - have constructors emitted.) */ - if (GetFlag(n, "feature:csdowncast")) { - String *downcast_method = Swig_name_member(getNSpace(), proxy_class_name, "SWIGDowncast"); - String *wname = Swig_name_wrapper(downcast_method); - - String *norm_name = SwigType_namestr(Getattr(n, "name")); - - Printf(imclass_class_code, " public final static native %s %s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, downcast_method); - - Wrapper *dcast_wrap = NewWrapper(); - - Printf(dcast_wrap->def, "SWIGEXPORT jobject SWIGSTDCALL %s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {", wname); - Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n"); - Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n"); - Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name); - Printf(dcast_wrap->code, " if (obj) director = dynamic_cast(obj);\n"); - Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n"); - Printf(dcast_wrap->code, " return jresult;\n"); - Printf(dcast_wrap->code, "}\n"); - - Wrapper_print(dcast_wrap, f_wrappers); - DelWrapper(dcast_wrap); - - Delete(norm_name); - Delete(wname); - Delete(downcast_method); - } - if (f_interface) { Printv(f_interface, interface_class_code, "}\n", NIL); addCloseNamespace(nspace, f_interface); @@ -2426,21 +2402,8 @@ public: Printf(function_code, " %s ", methodmods); if (!is_smart_pointer()) { // Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required. - if (Node *base_ovr = Getattr(n, "override")) { - if (GetFlag(n, "isextendmember")) + if (Getattr(n, "override")) Printf(function_code, "override "); - else { - Node* base = parentNode(base_ovr); - bool ovr = false; - for (Node* direct_base = Getattr(parentNode(n), "direct_base"); direct_base; direct_base = Getattr(direct_base, "direct_base")) { - if (direct_base == base) { // "override" only applies if the base was not discarded (e.g. in case of multiple inheritance or via "ignore") - ovr = true; - break; - } - } - Printf(function_code, ovr ? "override " : "virtual "); - } - } else if (checkAttribute(n, "storage", "virtual")) Printf(function_code, "virtual "); if (Getattr(n, "hides")) @@ -2843,7 +2806,8 @@ public: /* Insert the csconstruct typemap, doing the replacement for $directorconnect, as needed */ Hash *attributes = NewHash(); - String *construct_tm = Copy(typemapLookup(n, "csconstruct", Getattr(n, "name"), + String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj"); + String *construct_tm = Copy(typemapLookup(n, "csconstruct", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF, attributes)); if (construct_tm) { if (!feature_director) { @@ -2921,7 +2885,11 @@ public: if (proxy_flag) { Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL); + const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); + if (methodmods) + Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods); } + return SWIG_OK; } @@ -3602,6 +3570,24 @@ public: return tm; } + /* ----------------------------------------------------------------------------- + * typemapExists() + * n - for input only and must contain info for Getfile(n) and Getline(n) to work + * tmap_method - typemap method name + * type - typemap type to lookup + * returns found typemap or NULL if not found + * ----------------------------------------------------------------------------- */ + + const String *typemapExists(Node *n, const_String_or_char_ptr tmap_method, SwigType *type) { + Node *node = NewHash(); + Setattr(node, "type", type); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0); + Delete(node); + return tm; + } + /* ----------------------------------------------------------------------------- * canThrow() * Determine whether the code in the typemap can throw a C# exception. @@ -3764,16 +3750,13 @@ public: Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", smartptr, smartptr); Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n"); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); - } - else { + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); + } else { Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName); } - // TODO: if statement not needed?? - Java too - Printf(code_wrap->code, " if (director) {\n"); - Printf(code_wrap->code, " director->swig_connect_director("); + Printf(code_wrap->code, " director->swig_connect_director("); for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) { UpcallData *udata = Getitem(dmethods_seq, i); @@ -3790,7 +3773,6 @@ public: Printf(code_wrap->def, ") {\n"); Printf(code_wrap->code, ");\n"); Printf(imclass_class_code, ");\n"); - Printf(code_wrap->code, " }\n"); Printf(code_wrap->code, "}\n"); Wrapper_print(code_wrap, f_wrappers); @@ -3856,7 +3838,7 @@ public: qualified_return = SwigType_rcaststr(returntype, "c_result"); - if (!is_void && !ignored_method) { + if (!is_void && (!ignored_method || pure_virtual)) { if (!SwigType_isclass(returntype)) { if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); @@ -3876,15 +3858,17 @@ public: /* If returning a reference, initialize the pointer to a sane default - if a C# exception occurs, then the pointer returns something other than a NULL-initialized reference. */ - String *non_ref_type = Copy(returntype); + SwigType *noref_type = SwigType_del_reference(Copy(returntype)); + String *noref_ltype = SwigType_lstr(noref_type, 0); + String *return_ltype = SwigType_lstr(returntype, 0); - /* Remove reference and const qualifiers */ - Replaceall(non_ref_type, "r.", ""); - Replaceall(non_ref_type, "q(const).", ""); - Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL); - Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL); - - Delete(non_ref_type); + Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL); + Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL); + Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype); + Printf(w->code, "c_result = &result_default;\n"); + Delete(return_ltype); + Delete(noref_ltype); + Delete(noref_type); } Delete(base_typename); @@ -3916,9 +3900,13 @@ public: Printf(director_delegate_definitions, " %s\n", im_directoroutattributes); } - Printf(callback_def, " private %s SwigDirector%s(", tm, overloaded_name); - if (!ignored_method) - Printf(director_delegate_definitions, " public delegate %s", tm); + Printf(callback_def, " private %s SwigDirectorMethod%s(", tm, overloaded_name); + if (!ignored_method) { + const String *csdirectordelegatemodifiers = Getattr(n, "feature:csdirectordelegatemodifiers"); + String *modifiers = (csdirectordelegatemodifiers ? NewStringf("%s%s", csdirectordelegatemodifiers, Len(csdirectordelegatemodifiers) > 0 ? " " : "") : NewStringf("public ")); + Printf(director_delegate_definitions, " %sdelegate %s", modifiers, tm); + Delete(modifiers); + } } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0)); } @@ -3942,7 +3930,7 @@ public: Swig_typemap_attach_parms("ctype", l, 0); Swig_typemap_attach_parms("imtype", l, 0); Swig_typemap_attach_parms("cstype", l, 0); - Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorin", l, w); Swig_typemap_attach_parms("csdirectorin", l, 0); Swig_typemap_attach_parms("directorargout", l, w); @@ -3961,7 +3949,11 @@ public: } Delete(super_call); } else { - Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + if (!is_void) + Printf(w->code, "return %s;", qualified_return); + else if (!ignored_method) + Printf(w->code, "return;\n"); } if (!ignored_method) @@ -4119,15 +4111,19 @@ public: /* header declaration, start wrapper definition */ String *target; SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); - target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); + target = Swig_method_decl(rtype, decl, qualified_name, l, 0); Printf(w->def, "%s", target); Delete(qualified_name); Delete(target); - target = Swig_method_decl(rtype, decl, name, l, 0, 1); + target = Swig_method_decl(rtype, decl, name, l, 1); Printf(declaration, " virtual %s", target); Delete(target); // Add any exception specifications to the methods in the director class + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = NULL; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { int gencomma = 0; @@ -4336,7 +4332,7 @@ public: /* constructor */ { String *basetype = Getattr(parent, "classtype"); - String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 0); + String *target = Swig_method_decl(0, decl, dirclassname, parms, 0); String *call = Swig_csuperclass_call(0, basetype, superparms); Printf(f_directors, "%s::%s : %s, %s {\n", dirclassname, target, call, Getattr(parent, "director:ctor")); @@ -4349,7 +4345,7 @@ public: /* constructor header */ { - String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 1); + String *target = Swig_method_decl(0, decl, dirclassname, parms, 1); Printf(f_directors_h, " %s;\n", target); Delete(target); } @@ -4445,9 +4441,12 @@ public: String *dirclassname = directorClassName(current_class); Wrapper *w = NewWrapper(); - if (Getattr(n, "throw")) { - Printf(f_directors_h, " virtual ~%s() throw ();\n", dirclassname); - Printf(w->def, "%s::~%s() throw () {\n", dirclassname, dirclassname); + if (Getattr(n, "noexcept")) { + Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname); + Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname); + } else if (Getattr(n, "throw")) { + Printf(f_directors_h, " virtual ~%s() throw();\n", dirclassname); + Printf(w->def, "%s::~%s() throw() {\n", dirclassname, dirclassname); } else { Printf(f_directors_h, " virtual ~%s();\n", dirclassname); Printf(w->def, "%s::~%s() {\n", dirclassname, dirclassname); diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index ec66ebed2..5e82dfda3 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -717,9 +717,20 @@ public: * D::insertDirective() * --------------------------------------------------------------------------- */ virtual int insertDirective(Node *n) { + int ret = SWIG_OK; String *code = Getattr(n, "code"); + String *section = Getattr(n, "section"); replaceModuleVariables(code); - return Language::insertDirective(n); + + if (!ImportMode && (Cmp(section, "proxycode") == 0)) { + if (proxy_class_body_code) { + Swig_typemap_replace_embedded_typemap(code, n); + Printv(proxy_class_body_code, code, NIL); + } + } else { + ret = Language::insertDirective(n); + } + return ret; } /* --------------------------------------------------------------------------- @@ -978,7 +989,7 @@ public: // Smart pointer classes do not mirror the inheritance hierarchy of the // underlying types, so aliasing the base class methods in is not required // for them. - // DMD BUG: We have to emit the alias after the last function becasue + // DMD BUG: We have to emit the alias after the last function because // taking a delegate in the overload checking code fails otherwise // (http://d.puremagic.com/issues/show_bug.cgi?id=4860). if (!Getattr(n, "sym:nextSibling") && !is_smart_pointer() && @@ -1216,8 +1227,9 @@ public: // Insert the dconstructor typemap (replacing $directorconnect as needed). Hash *attributes = NewHash(); + String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj"); String *construct_tm = Copy(lookupCodeTypemap(n, "dconstructor", - Getattr(n, "name"), WARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF, attributes)); + typemap_lookup_type, WARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF, attributes)); if (construct_tm) { const bool use_director = (parentNode(n) && Swig_directorclass(n)); if (!use_director) { @@ -1287,7 +1299,12 @@ public: virtual int destructorHandler(Node *n) { Language::destructorHandler(n); String *symname = Getattr(n, "sym:name"); + Printv(destructor_call, im_dmodule_fq_name, ".", Swig_name_destroy(getNSpace(),symname), "(cast(void*)swigCPtr)", NIL); + const String *methodmods = Getattr(n, "feature:d:methodmodifiers"); + if (methodmods) + Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods); + return SWIG_OK; } @@ -1465,7 +1482,7 @@ public: } Delete(attributes); - // Retrive the override value set via %dconstvalue, if any. + // Retrieve the override value set via %dconstvalue, if any. String *override_value = Getattr(n, "feature:d:constvalue"); if (override_value) { Printf(constants_code, "%s;\n", override_value); @@ -1964,7 +1981,7 @@ public: qualified_return = SwigType_rcaststr(returntype, "c_result"); - if (!is_void && !ignored_method) { + if (!is_void && (!ignored_method || pure_virtual)) { if (!SwigType_isclass(returntype)) { if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); @@ -1984,15 +2001,17 @@ public: /* If returning a reference, initialize the pointer to a sane default - if a D exception occurs, then the pointer returns something other than a NULL-initialized reference. */ - String *non_ref_type = Copy(returntype); + SwigType *noref_type = SwigType_del_reference(Copy(returntype)); + String *noref_ltype = SwigType_lstr(noref_type, 0); + String *return_ltype = SwigType_lstr(returntype, 0); - /* Remove reference and const qualifiers */ - Replaceall(non_ref_type, "r.", ""); - Replaceall(non_ref_type, "q(const).", ""); - Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL); - Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL); - - Delete(non_ref_type); + Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL); + Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL); + Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype); + Printf(w->code, "c_result = &result_default;\n"); + Delete(return_ltype); + Delete(noref_ltype); + Delete(noref_type); } Delete(base_typename); @@ -2047,7 +2066,7 @@ public: Swig_typemap_attach_parms("ctype", l, 0); Swig_typemap_attach_parms("imtype", l, 0); Swig_typemap_attach_parms("dtype", l, 0); - Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorin", l, w); Swig_typemap_attach_parms("ddirectorin", l, 0); Swig_typemap_attach_parms("directorargout", l, w); @@ -2066,7 +2085,11 @@ public: } Delete(super_call); } else { - Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + if (!is_void) + Printf(w->code, "return %s;", qualified_return); + else if (!ignored_method) + Printf(w->code, "return;\n"); } if (!ignored_method) @@ -2197,15 +2220,19 @@ public: /* header declaration, start wrapper definition */ String *target; SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); - target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); + target = Swig_method_decl(rtype, decl, qualified_name, l, 0); Printf(w->def, "%s", target); Delete(qualified_name); Delete(target); - target = Swig_method_decl(rtype, decl, name, l, 0, 1); + target = Swig_method_decl(rtype, decl, name, l, 1); Printf(declaration, " virtual %s", target); Delete(target); // Add any exception specifications to the methods in the director class + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = NULL; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { int gencomma = 0; @@ -2417,7 +2444,7 @@ public: /* constructor */ { String *basetype = Getattr(parent, "classtype"); - String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 0); + String *target = Swig_method_decl(0, decl, dirclassname, parms, 0); String *call = Swig_csuperclass_call(0, basetype, superparms); String *classtype = SwigType_namestr(Getattr(n, "name")); @@ -2432,7 +2459,7 @@ public: /* constructor header */ { - String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 1); + String *target = Swig_method_decl(0, decl, dirclassname, parms, 1); Printf(f_directors_h, " %s;\n", target); Delete(target); } @@ -2472,9 +2499,12 @@ public: String *dirclassname = directorClassName(current_class); Wrapper *w = NewWrapper(); - if (Getattr(n, "throw")) { - Printf(f_directors_h, " virtual ~%s() throw ();\n", dirclassname); - Printf(w->def, "%s::~%s() throw () {\n", dirclassname, dirclassname); + if (Getattr(n, "noexcept")) { + Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname); + Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname); + } else if (Getattr(n, "throw")) { + Printf(f_directors_h, " virtual ~%s() throw();\n", dirclassname); + Printf(w->def, "%s::~%s() throw() {\n", dirclassname, dirclassname); } else { Printf(f_directors_h, " virtual ~%s();\n", dirclassname); Printf(w->def, "%s::~%s() {\n", dirclassname, dirclassname); @@ -3244,17 +3274,20 @@ private: // attribute called »methodname«. const String *tm = NULL; - String *dispose_methodname; - String *dispose_methodmodifiers; + const String *dispose_methodname; + const String *dispose_methodmodifiers; + const String *dispose_parameters; attributes = NewHash(); if (derived) { tm = lookupCodeTypemap(n, "ddispose_derived", typemap_lookup_type, WARN_NONE, attributes); dispose_methodname = Getattr(attributes, "tmap:ddispose_derived:methodname"); dispose_methodmodifiers = Getattr(attributes, "tmap:ddispose_derived:methodmodifiers"); + dispose_parameters = Getattr(attributes, "tmap:ddispose_derived:parameters"); } else { tm = lookupCodeTypemap(n, "ddispose", typemap_lookup_type, WARN_NONE, attributes); dispose_methodname = Getattr(attributes, "tmap:ddispose:methodname"); dispose_methodmodifiers = Getattr(attributes, "tmap:ddispose:methodmodifiers"); + dispose_parameters = Getattr(attributes, "tmap:ddispose:parameters"); } if (tm && *Char(tm)) { @@ -3268,6 +3301,8 @@ private: "No methodmodifiers attribute defined in ddispose%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name); } + if (!dispose_parameters) + dispose_parameters = empty_string; } if (tm) { @@ -3288,9 +3323,13 @@ private: } if (*Char(dispose_code)) { - Printv(body, "\n", dispose_methodmodifiers, - (derived ? " override" : ""), " void ", dispose_methodname, "() ", - dispose_code, "\n", NIL); + Printv(body, "\n", NIL); + const String *methodmods = Getattr(n, "destructmethodmodifiers"); + if (methodmods) + Printv(body, methodmods, NIL); + else + Printv(body, dispose_methodmodifiers, (derived ? " override" : ""), NIL); + Printv(body, " void ", dispose_methodname, "(", dispose_parameters, ") ", dispose_code, "\n", NIL); } } @@ -3545,10 +3584,9 @@ private: Printf(code_wrap->def, "SWIGEXPORT void D_%s(void *objarg, void *dobj", connect_name); Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName); - Printf(code_wrap->code, " if (director) {\n"); - Printf(code_wrap->code, " director->swig_connect_director(dobj"); + Printf(code_wrap->code, " director->swig_connect_director(dobj"); for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) { UpcallData *udata = Getitem(dmethods_seq, i); @@ -3562,7 +3600,6 @@ private: Printf(code_wrap->def, ") {\n"); Printf(code_wrap->code, ");\n"); Printf(im_dmodule_code, ") %s;\n", connect_name); - Printf(code_wrap->code, " }\n"); Printf(code_wrap->code, "}\n"); Wrapper_print(code_wrap, f_wrappers); @@ -4321,7 +4358,7 @@ private: * * Determines whether the class the passed function node belongs to overrides * all the overlaods for the passed function node defined somewhere up the - * inheritance hierachy. + * inheritance hierarchy. * --------------------------------------------------------------------------- */ bool areAllOverloadsOverridden(Node *n) const { List *base_list = Getattr(parentNode(n), "bases"); @@ -4346,7 +4383,7 @@ private: } // We try to find at least a single overload which exists in the base class - // so we can progress up the inheritance hierachy even if there have been + // so we can progress up the inheritance hierarchy even if there have been // new overloads introduced after the topmost class. Node *base_function = NULL; String *symname = Getattr(n, "sym:name"); @@ -4372,7 +4409,7 @@ private: !(Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode())) { // If the base class function is »protected« and were are not in // director mode, it is not emitted to the base class and thus we do - // not count it. Otherwise, we would run into issues if the visiblity + // not count it. Otherwise, we would run into issues if the visibility // of some functions was changed from protected to public in a child // class with the using directive. continue; diff --git a/Source/Modules/directors.cxx b/Source/Modules/directors.cxx index 2fdda5a12..a91d5fd9a 100644 --- a/Source/Modules/directors.cxx +++ b/Source/Modules/directors.cxx @@ -15,12 +15,12 @@ #include "swigmod.h" -/* Swig_csuperclass_call() +/* ----------------------------------------------------------------------------- + * Swig_csuperclass_call() * * Generates a fully qualified method call, including the full parameter list. * e.g. "base::method(i, j)" - * - */ + * ----------------------------------------------------------------------------- */ String *Swig_csuperclass_call(String *base, String *method, ParmList *l) { String *call = NewString(""); @@ -44,12 +44,12 @@ String *Swig_csuperclass_call(String *base, String *method, ParmList *l) { return call; } -/* Swig_class_declaration() +/* ----------------------------------------------------------------------------- + * Swig_class_declaration() * * Generate the start of a class/struct declaration. * e.g. "class myclass" - * - */ + * ----------------------------------------------------------------------------- */ String *Swig_class_declaration(Node *n, String *name) { if (!name) { @@ -61,18 +61,22 @@ String *Swig_class_declaration(Node *n, String *name) { return result; } +/* ----------------------------------------------------------------------------- + * Swig_class_name() + * ----------------------------------------------------------------------------- */ + String *Swig_class_name(Node *n) { String *name; name = Copy(Getattr(n, "sym:name")); return name; } -/* Swig_director_declaration() +/* ----------------------------------------------------------------------------- + * Swig_director_declaration() * * Generate the full director class declaration, complete with base classes. * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {" - * - */ + * ----------------------------------------------------------------------------- */ String *Swig_director_declaration(Node *n) { String *classname = Swig_class_name(n); @@ -87,6 +91,10 @@ String *Swig_director_declaration(Node *n) { } +/* ----------------------------------------------------------------------------- + * Swig_method_call() + * ----------------------------------------------------------------------------- */ + String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms) { String *func; int i = 0; @@ -115,153 +123,67 @@ String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms) { return func; } -/* Swig_method_decl +/* ----------------------------------------------------------------------------- + * Swig_method_decl() * - * Misnamed and misappropriated! Taken from SWIG's type string manipulation utilities - * and modified to generate full (or partial) type qualifiers for method declarations, - * local variable declarations, and return value casting. More importantly, it merges - * parameter type information with actual parameter names to produce a complete method - * declaration that fully mirrors the original method declaration. - * - * There is almost certainly a saner way to do this. - * - * This function needs to be cleaned up and possibly split into several smaller - * functions. For instance, attaching default names to parameters should be done in a - * separate function. - * - */ + * Return a stringified version of a C/C++ declaration. + * ----------------------------------------------------------------------------- */ -String *Swig_method_decl(SwigType *rettype, SwigType *decl, const_String_or_char_ptr id, List *args, int strip, int values) { - String *result; - List *elements; - String *element = 0, *nextelement; - int is_const = 0; - int nelements, i; - int is_func = 0; +String *Swig_method_decl(SwigType *return_base_type, SwigType *decl, const_String_or_char_ptr id, List *args, int default_args) { + String *result = NewString(""); + bool conversion_operator = Strstr(id, "operator ") != 0 && !return_base_type; + + Parm *parm = args; int arg_idx = 0; - - if (id) { - result = NewString(Char(id)); - } else { - result = NewString(""); - } - - elements = SwigType_split(decl); - nelements = Len(elements); - if (nelements > 0) { - element = Getitem(elements, 0); - } - for (i = 0; i < nelements; i++) { - if (i < (nelements - 1)) { - nextelement = Getitem(elements, i + 1); - } else { - nextelement = 0; + while (parm) { + String *type = Getattr(parm, "type"); + String *name = Getattr(parm, "name"); + if (!name && Cmp(type, "void")) { + name = NewString(""); + Printf(name, "arg%d", arg_idx++); + Setattr(parm, "name", name); } - if (SwigType_isqualifier(element)) { - int skip = 0; - DOH *q = 0; - if (!strip) { - q = SwigType_parm(element); - if (!Cmp(q, "const")) { - is_const = 1; - is_func = SwigType_isfunction(nextelement); - if (is_func) - skip = 1; - skip = 1; - } - if (!skip) { - Insert(result, 0, " "); - Insert(result, 0, q); - } - Delete(q); - } - } else if (SwigType_isfunction(element)) { - Parm *parm; - String *p; - Append(result, "("); - parm = args; - while (parm != 0) { - String *type = Getattr(parm, "type"); - String *name = Getattr(parm, "name"); - if (!name && Cmp(type, "void")) { - name = NewString(""); - Printf(name, "arg%d", arg_idx++); - Setattr(parm, "name", name); - } - if (!name) { - name = NewString(""); - } - p = SwigType_str(type, name); - Append(result, p); - String *value = Getattr(parm, "value"); - if (values && (value != 0)) { - Printf(result, " = %s", value); - } - parm = nextSibling(parm); - if (parm != 0) - Append(result, ", "); - } - Append(result, ")"); - } else if (rettype) { // This check is intended for conversion operators to a pointer/reference which needs the pointer/reference ignoring in the declaration - if (SwigType_ispointer(element)) { - Insert(result, 0, "*"); - if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { - Insert(result, 0, "("); - Append(result, ")"); - } - } else if (SwigType_ismemberpointer(element)) { - String *q; - q = SwigType_parm(element); - Insert(result, 0, "::*"); - Insert(result, 0, q); - if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { - Insert(result, 0, "("); - Append(result, ")"); - } - Delete(q); - } else if (SwigType_isreference(element)) { - Insert(result, 0, "&"); - } else if (SwigType_isarray(element)) { - DOH *size; - Append(result, "["); - size = SwigType_parm(element); - Append(result, size); - Append(result, "]"); - Delete(size); - } else { - if (Strcmp(element, "v(...)") == 0) { - Insert(result, 0, "..."); - } else { - String *bs = SwigType_namestr(element); - Insert(result, 0, " "); - Insert(result, 0, bs); - Delete(bs); - } - } - } - element = nextelement; + parm = nextSibling(parm); } - Delete(elements); + String *rettype = Copy(decl); + String *quals = SwigType_pop_function_qualifiers(rettype); + String *qualifiers = 0; + if (quals) + qualifiers = SwigType_str(quals, 0); - if (is_const) { - if (is_func) { - Append(result, " "); - Append(result, "const"); - } else { - Insert(result, 0, "const "); - } - } + String *popped_decl = SwigType_pop_function(rettype); + if (return_base_type) + Append(rettype, return_base_type); - Chop(result); - - if (rettype) { - Insert(result, 0, " "); + if (!conversion_operator) { + SwigType *rettype_stripped = SwigType_strip_qualifiers(rettype); String *rtype = SwigType_str(rettype, 0); - Insert(result, 0, rtype); + Append(result, rtype); + if (SwigType_issimple(rettype_stripped) && return_base_type) + Append(result, " "); Delete(rtype); + Delete(rettype_stripped); } + if (id) + Append(result, id); + + String *args_string = default_args ? ParmList_str_defaultargs(args) : ParmList_str(args); + Printv(result, "(", args_string, ")", NIL); + + if (qualifiers) + Printv(result, " ", qualifiers, NIL); + + // Reformat result to how it has been historically + Replaceall(result, ",", ", "); + Replaceall(result, "=", " = "); + + Delete(args_string); + Delete(popped_decl); + Delete(qualifiers); + Delete(quals); + Delete(rettype); return result; } @@ -272,6 +194,7 @@ String *Swig_method_decl(SwigType *rettype, SwigType *decl, const_String_or_char * to add an extra dynamic_cast to call the public C++ wrapper in the director class. * Also for non-static protected members when the allprotected option is on. * ----------------------------------------------------------------------------- */ + void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f) { // TODO: why is the storage element removed in staticmemberfunctionHandler ?? if ((!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) || @@ -290,13 +213,13 @@ void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f) { } } -/* ------------------------------------------------------------ +/* ----------------------------------------------------------------------------- * Swig_director_parms_fixup() * * For each parameter in the C++ member function, copy the parameter name * to its "lname"; this ensures that Swig_typemap_attach_parms() will do * the right thing when it sees strings like "$1" in "directorin" typemaps. - * ------------------------------------------------------------ */ + * ----------------------------------------------------------------------------- */ void Swig_director_parms_fixup(ParmList *parms) { Parm *p; diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx index 7c2607fc8..7a4c2dcfb 100644 --- a/Source/Modules/emit.cxx +++ b/Source/Modules/emit.cxx @@ -12,6 +12,7 @@ * ----------------------------------------------------------------------------- */ #include "swigmod.h" +#include "cparse.h" /* ----------------------------------------------------------------------------- * emit_return_variable() @@ -112,9 +113,8 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) { /* This is compatibility code to deal with the deprecated "ignore" typemap */ Parm *p = l; Parm *np; - String *tm; while (p) { - tm = Getattr(p, "tmap:in"); + String *tm = Getattr(p, "tmap:in"); if (tm && checkAttribute(p, "tmap:in:numinputs", "0")) { Replaceall(tm, "$target", Getattr(p, "lname")); Printv(f->code, tm, "\n", NIL); @@ -134,7 +134,6 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) { /* Perform a sanity check on "in" and "freearg" typemaps. These must exactly match to avoid chaos. If a mismatch occurs, we nuke the freearg typemap */ - { Parm *p = l; Parm *npin, *npfreearg; @@ -189,13 +188,45 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) { p = lp; while (p) { if (SwigType_isvarargs(Getattr(p, "type"))) { + // Mark the head of the ParmList that it has varargs Setattr(l, "emit:varargs", lp); +//Printf(stdout, "setting emit:varargs %s ... %s +++ %s\n", Getattr(l, "emit:varargs"), Getattr(l, "type"), Getattr(p, "type")); break; } p = nextSibling(p); } } } + + /* + * An equivalent type can be used in the typecheck typemap for SWIG to detect the overloading of equivalent + * target language types. This is primarily for the smartptr feature, where a pointer and a smart pointer + * are seen as equivalent types in the target language. + */ + { + Parm *p = l; + while (p) { + String *tm = Getattr(p, "tmap:typecheck"); + if (tm) { + String *equivalent = Getattr(p, "tmap:typecheck:equivalent"); + if (equivalent) { + String *precedence = Getattr(p, "tmap:typecheck:precedence"); + if (precedence && Strcmp(precedence, "0") != 0) + Swig_error(Getfile(tm), Getline(tm), "The 'typecheck' typemap for %s contains an 'equivalent' attribute for a 'precedence' that is not set to SWIG_TYPECHECK_POINTER or 0.\n", SwigType_str(Getattr(p, "type"), 0)); + SwigType *cpt = Swig_cparse_type(equivalent); + if (cpt) { + Setattr(p, "equivtype", cpt); + Delete(cpt); + } else { + Swig_error(Getfile(tm), Getline(tm), "Invalid type (%s) in 'equivalent' attribute in 'typecheck' typemap for type %s.\n", equivalent, SwigType_str(Getattr(p, "type"), 0)); + } + } + p = Getattr(p, "tmap:typecheck:next"); + } else { + p = nextSibling(p); + } + } + } } /* ----------------------------------------------------------------------------- @@ -300,7 +331,8 @@ int emit_num_required(ParmList *parms) { /* ----------------------------------------------------------------------------- * emit_isvarargs() * - * Checks if a function is a varargs function + * Checks if a ParmList is a parameter list containing varargs. + * This function requires emit_attach_parmmaps to have been called beforehand. * ----------------------------------------------------------------------------- */ int emit_isvarargs(ParmList *p) { @@ -311,6 +343,28 @@ int emit_isvarargs(ParmList *p) { return 0; } +/* ----------------------------------------------------------------------------- + * emit_isvarargs_function() + * + * Checks for varargs in a function/constructor (can be overloaded) + * ----------------------------------------------------------------------------- */ + +bool emit_isvarargs_function(Node *n) { + bool has_varargs = false; + Node *over = Getattr(n, "sym:overloaded"); + if (over) { + for (Node *sibling = over; sibling; sibling = Getattr(sibling, "sym:nextSibling")) { + if (ParmList_has_varargs(Getattr(sibling, "parms"))) { + has_varargs = true; + break; + } + } + } else { + has_varargs = ParmList_has_varargs(Getattr(n, "parms")) ? true : false; + } + return has_varargs; +} + /* ----------------------------------------------------------------------------- * void emit_mark_vararg_parms() * @@ -454,29 +508,29 @@ String *emit_action(Node *n) { if (catchlist) { int unknown_catch = 0; int has_varargs = 0; - Printf(eaction, "}\n"); + Printf(eaction, "}"); for (Parm *ep = catchlist; ep; ep = nextSibling(ep)) { String *em = Swig_typemap_lookup("throws", ep, "_e", 0); if (em) { SwigType *et = Getattr(ep, "type"); SwigType *etr = SwigType_typedef_resolve_all(et); if (SwigType_isreference(etr) || SwigType_ispointer(etr) || SwigType_isarray(etr)) { - Printf(eaction, "catch(%s) {", SwigType_str(et, "_e")); + Printf(eaction, " catch(%s) {", SwigType_str(et, "_e")); } else if (SwigType_isvarargs(etr)) { - Printf(eaction, "catch(...) {"); + Printf(eaction, " catch(...) {"); has_varargs = 1; } else { - Printf(eaction, "catch(%s) {", SwigType_str(et, "&_e")); + Printf(eaction, " catch(%s) {", SwigType_str(et, "&_e")); } Printv(eaction, em, "\n", NIL); - Printf(eaction, "}\n"); + Printf(eaction, "}"); } else { Swig_warning(WARN_TYPEMAP_THROW, Getfile(n), Getline(n), "No 'throws' typemap defined for exception type '%s'\n", SwigType_str(Getattr(ep, "type"), 0)); unknown_catch = 1; } } if (unknown_catch && !has_varargs) { - Printf(eaction, "catch(...) { throw; }\n"); + Printf(eaction, " catch(...) {\nthrow;\n}"); } } diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index 7fa9b2670..0163f71df 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -125,6 +125,8 @@ class GO:public Language { String *prefix_option; // -fgo-pkgpath option. String *pkgpath_option; + // Prefix for translating %import directive to import statements. + String *import_prefix; // Whether to use a shared library. bool use_shlib; // Name of shared library to import. @@ -199,11 +201,12 @@ class GO:public Language { public: GO():package(NULL), module(NULL), - cgo_flag(false), + cgo_flag(true), gccgo_flag(false), go_prefix(NULL), prefix_option(NULL), pkgpath_option(NULL), + import_prefix(NULL), use_shlib(false), soname(NULL), intgo_type_size(0), @@ -269,6 +272,9 @@ private: } else if (strcmp(argv[i], "-cgo") == 0) { Swig_mark_arg(i); cgo_flag = true; + } else if (strcmp(argv[i], "-no-cgo") == 0) { + Swig_mark_arg(i); + cgo_flag = false; } else if (strcmp(argv[i], "-gccgo") == 0) { Swig_mark_arg(i); gccgo_flag = true; @@ -290,6 +296,15 @@ private: } else { Swig_arg_error(); } + } else if (strcmp(argv[i], "-import-prefix") == 0) { + if (argv[i + 1]) { + import_prefix = NewString(argv[i + 1]); + Swig_mark_arg(i); + Swig_mark_arg(i + 1); + i++; + } else { + Swig_arg_error(); + } } else if (strcmp(argv[i], "-use-shlib") == 0) { Swig_mark_arg(i); use_shlib = true; @@ -615,6 +630,12 @@ private: Language::top(n); + if (directorsEnabled()) { + // Insert director runtime into the f_runtime file (make it occur before %header section) + Swig_insert_file("director_common.swg", f_c_runtime); + Swig_insert_file("director.swg", f_c_runtime); + } + Delete(go_imports); // Write out definitions for the types not defined by SWIG. @@ -734,7 +755,11 @@ private: if (modname) { if (!Getattr(go_imports, modname)) { Setattr(go_imports, modname, modname); - Printv(f_go_imports, "import \"", modname, "\"\n", NULL); + Printv(f_go_imports, "import \"", NULL); + if (import_prefix) { + Printv(f_go_imports, import_prefix, "/", NULL); + } + Printv(f_go_imports, modname, "\"\n", NULL); } imported_package = modname; saw_import = true; @@ -990,7 +1015,7 @@ private: * overname: The overload string for overloaded function. * wname: The SWIG wrapped name--the name of the C function. * base: A list of the names of base classes, in the case where this - * is is a vritual method not defined in the current class. + * is a virtual method not defined in the current class. * parms: The parameters. * result: The result type. * is_static: Whether this is a static method or member. @@ -2445,7 +2470,8 @@ private: } String *code = Copy(Getattr(n, "wrap:action")); - Replaceall(code, Getattr(parms, "lname"), current); + Replace(code, Getattr(parms, "lname"), current, DOH_REPLACE_ANY | DOH_REPLACE_ID); + Delete(current); Printv(actioncode, code, "\n", NULL); } @@ -2598,6 +2624,14 @@ private: Replaceall(f->code, "$cleanup", cleanup); Delete(cleanup); + /* See if there is any return cleanup code */ + String *tm; + if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) { + Replaceall(tm, "$source", Swig_cresult_name()); + Printf(f->code, "%s\n", tm); + Delete(tm); + } + Replaceall(f->code, "$symname", Getattr(n, "sym:name")); } @@ -2797,34 +2831,53 @@ private: return SWIG_NOWRAP; } - String *get = NewString(""); - Printv(get, Swig_cresult_name(), " = ", NULL); - - char quote; - if (Getattr(n, "wrappedasconstant")) { - quote = '\0'; - } else if (SwigType_type(type) == T_CHAR) { - quote = '\''; - } else if (SwigType_type(type) == T_STRING) { - Printv(get, "(char *)", NULL); - quote = '"'; + String *rawval = Getattr(n, "rawval"); + if (rawval && Len(rawval)) { + // Based on Swig_VargetToFunction + String *nname = NewStringf("(%s)", rawval); + String *call; + if (SwigType_isclass(type)) { + call = NewStringf("%s", nname); + } else { + call = SwigType_lcaststr(type, nname); + } + String *cres = Swig_cresult(type, Swig_cresult_name(), call); + Setattr(n, "wrap:action", cres); + Delete(nname); + Delete(call); + Delete(cres); } else { - quote = '\0'; + String *get = NewString(""); + Printv(get, Swig_cresult_name(), " = ", NULL); + + char quote; + if (Getattr(n, "wrappedasconstant")) { + quote = '\0'; + } else if (SwigType_type(type) == T_CHAR) { + quote = '\''; + } else if (SwigType_type(type) == T_STRING) { + Printv(get, "(char *)", NULL); + quote = '"'; + } else { + quote = '\0'; + } + + if (quote != '\0') { + Printf(get, "%c", quote); + } + + Printv(get, Getattr(n, "value"), NULL); + + if (quote != '\0') { + Printf(get, "%c", quote); + } + + Printv(get, ";\n", NULL); + + Setattr(n, "wrap:action", get); + Delete(get); } - if (quote != '\0') { - Printf(get, "%c", quote); - } - - Printv(get, Getattr(n, "value"), NULL); - - if (quote != '\0') { - Printf(get, "%c", quote); - } - - Printv(get, ";\n", NULL); - Setattr(n, "wrap:action", get); - String *sname = Copy(symname); if (class_name) { Append(sname, "_"); @@ -3829,12 +3882,11 @@ private: String *cxx_director_name = NewString("SwigDirector_"); Append(cxx_director_name, class_name); - String *decl = Swig_method_decl(NULL, Getattr(n, "decl"), - cxx_director_name, first_parm, 0, 0); + String *decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0); Printv(f_c_directors_h, " ", decl, ";\n", NULL); Delete(decl); - decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0, 0); + decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0); Printv(f_c_directors, cxx_director_name, "::", decl, "\n", NULL); Delete(decl); @@ -4559,7 +4611,7 @@ private: Append(upcall_method_name, overname); } SwigType *rtype = Getattr(n, "classDirectorMethods:type"); - String *upcall_decl = Swig_method_decl(rtype, Getattr(n, "decl"), upcall_method_name, parms, 0, 0); + String *upcall_decl = Swig_method_decl(rtype, Getattr(n, "decl"), upcall_method_name, parms, 0); Printv(f_c_directors_h, " ", upcall_decl, " {\n", NULL); Delete(upcall_decl); @@ -5007,13 +5059,13 @@ private: // Declare the method for the director class. SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); - String *decl = Swig_method_decl(rtype, Getattr(n, "decl"), Getattr(n, "name"), parms, 0, 0); + String *decl = Swig_method_decl(rtype, Getattr(n, "decl"), Getattr(n, "name"), parms, 0); Printv(f_c_directors_h, " virtual ", decl, NULL); Delete(decl); String *qname = NewString(""); Printv(qname, "SwigDirector_", class_name, "::", Getattr(n, "name"), NULL); - decl = Swig_method_decl(rtype, Getattr(n, "decl"), qname, parms, 0, 0); + decl = Swig_method_decl(rtype, Getattr(n, "decl"), qname, parms, 0); Printv(w->def, decl, NULL); Delete(decl); Delete(qname); @@ -5030,7 +5082,19 @@ private: Printv(w->def, " {\n", NULL); if (SwigType_type(result) != T_VOID) { - Wrapper_add_local(w, "c_result", SwigType_lstr(result, "c_result")); + if (!SwigType_isclass(result)) { + if (!(SwigType_ispointer(result) || SwigType_isreference(result))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(result, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(result, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(result, "c_result"), "= 0", NIL); + } + } else { + String *cres = SwigType_lstr(result, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); + } } if (!is_ignored) { @@ -5464,6 +5528,8 @@ private: *--------------------------------------------------------------------*/ String *buildThrow(Node *n) { + if (Getattr(n, "noexcept")) + return NewString("noexcept"); ParmList *throw_parm_list = Getattr(n, "throws"); if (!throw_parm_list && !Getattr(n, "throw")) return NULL; @@ -5893,7 +5959,7 @@ private: * * Given a C/C++ name, return a name in Go which will be exported. * If the first character is an upper case letter, this returns a - * copy of its argment. If the first character is a lower case + * copy of its argument. If the first character is a lower case * letter, this forces it to upper case. Otherwise, this prepends * 'X'. * ---------------------------------------------------------------------- */ @@ -6213,9 +6279,9 @@ private: Setattr(undefined_enum_types, t, ret); Delete(tt); } - } else if (SwigType_isfunctionpointer(type) || SwigType_isfunction(type)) { + } else if (SwigType_isfunctionpointer(t) || SwigType_isfunction(t)) { ret = NewString("_swig_fnptr"); - } else if (SwigType_ismemberpointer(type)) { + } else if (SwigType_ismemberpointer(t)) { ret = NewString("_swig_memberptr"); } else if (SwigType_issimple(t)) { Node *cn = classLookup(t); @@ -6932,9 +6998,11 @@ extern "C" Language *swig_go(void) { const char * const GO::usage = "\ Go Options (available with -go)\n\ -cgo - Generate cgo input files\n\ - -gccgo - Generate code for gccgo rather than 6g/8g\n\ + -no-cgo - Do not generate cgo input files\n\ + -gccgo - Generate code for gccgo rather than gc\n\ -go-pkgpath

      - Like gccgo -fgo-pkgpath option\n\ -go-prefix

      - Like gccgo -fgo-prefix option\n\ + -import-prefix

      - Prefix to add to %import directives\n\ -intgosize - Set size of Go int type--32 or 64 bits\n\ -package - Set name of the Go package to \n\ -use-shlib - Force use of a shared library\n\ diff --git a/Source/Modules/interface.cxx b/Source/Modules/interface.cxx index f6d4c955b..fee6cd7da 100644 --- a/Source/Modules/interface.cxx +++ b/Source/Modules/interface.cxx @@ -151,12 +151,14 @@ void Swig_interface_propagate_methods(Node *n) { for (Node *child = firstChild(n); child; child = nextSibling(child)) { if (Getattr(child, "interface:owner")) break; // at the end of the list are newly appended methods - if (checkAttribute(child, "name", name)) { - String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl")); - identically_overloaded_method = Strcmp(decl, this_decl_resolved) == 0; - Delete(decl); - if (identically_overloaded_method) - break; + if (Cmp(nodeType(child), "cdecl") == 0) { + if (checkAttribute(child, "name", name)) { + String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl")); + identically_overloaded_method = Strcmp(decl, this_decl_resolved) == 0; + Delete(decl); + if (identically_overloaded_method) + break; + } } } } diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index eb809ff59..259f23f8e 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -15,6 +15,7 @@ #include // for INT_MAX #include "cparse.h" #include +#include "javadoc.h" /* Hash type used for upcalls from C/C++ */ typedef DOH UpcallData; @@ -46,7 +47,9 @@ class JAVA:public Language { bool global_variable_flag; // Flag for when wrapping a global variable bool old_variable_names; // Flag for old style variable names in the intermediary class bool member_func_flag; // flag set when wrapping a member function - + bool doxygen; //flag for converting found doxygen to javadoc + bool comment_creation_chatter; //flag for getting information about where comments were created in java.cxx + String *imclass_name; // intermediary class name String *module_class_name; // module class name String *constants_interface_name; // constants interface name @@ -72,8 +75,8 @@ class JAVA:public Language { String *module_baseclass; //inheritance for module class from %pragma String *imclass_interfaces; //interfaces for intermediary class class from %pragma String *module_interfaces; //interfaces for module class from %pragma - String *imclass_class_modifiers; //class modifiers for intermediary class overriden by %pragma - String *module_class_modifiers; //class modifiers for module class overriden by %pragma + String *imclass_class_modifiers; //class modifiers for intermediary class overridden by %pragma + String *module_class_modifiers; //class modifiers for module class overridden by %pragma String *upcasts_code; //C++ casts for inheritance hierarchies C++ code String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code String *imclass_directors; // Intermediate class director code @@ -120,6 +123,8 @@ public: global_variable_flag(false), old_variable_names(false), member_func_flag(false), + doxygen(false), + comment_creation_chatter(false), imclass_name(NULL), module_class_name(NULL), constants_interface_name(NULL), @@ -164,11 +169,15 @@ public: director_multiple_inheritance = 0; director_language = 1; } + + ~JAVA() { + delete doxygenTranslator; + } /* ----------------------------------------------------------------------------- * constructIntermediateClassName() * - * Construct the fully qualified name of the intermidiate class and set + * Construct the fully qualified name of the intermediate class and set * the full_imclass_name attribute accordingly. * ----------------------------------------------------------------------------- */ void constructIntermediateClassName(Node *n) { @@ -256,6 +265,8 @@ public: SWIG_library_directory("java"); + int doxygen_translator_flags = 0; + // Look for certain command line options for (int i = 1; i < argc; i++) { if (argv[i]) { @@ -277,6 +288,16 @@ public: Printf(stderr, "Deprecated command line option: %s. Proxy classes are now generated by default.\n", argv[i]); Swig_mark_arg(i); proxy_flag = true; + } else if ((strcmp(argv[i], "-doxygen") == 0)) { + Swig_mark_arg(i); + doxygen = true; + scan_doxygen_comments = true; + } else if ((strcmp(argv[i], "-debug-doxygen-translator") == 0)) { + Swig_mark_arg(i); + doxygen_translator_flags |= DoxygenTranslator::debug_translator; + } else if ((strcmp(argv[i], "-debug-doxygen-parser") == 0)) { + Swig_mark_arg(i); + doxygen_translator_flags |= DoxygenTranslator::debug_parser; } else if ((strcmp(argv[i], "-noproxy") == 0)) { Swig_mark_arg(i); proxy_flag = false; @@ -300,6 +321,9 @@ public: } } } + + if (doxygen) + doxygenTranslator = new JavaDocConverter(doxygen_translator_flags); // Add a symbol to the parser for conditional compilation Preprocessor_define("SWIGJAVA 1", 0); @@ -567,6 +591,13 @@ public: if (module_imports) Printf(f_module, "%s\n", module_imports); + if (doxygen && doxygenTranslator->hasDocumentation(n)) { + String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0); + if (comment_creation_chatter) + Printf(f_module, "/* This was generated from top() */\n"); + Printv(f_module, Char(doxygen_comments), NIL); + Delete(doxygen_comments); + } if (Len(module_class_modifiers) > 0) Printf(f_module, "%s ", module_class_modifiers); Printf(f_module, "%s ", module_class_name); @@ -1246,6 +1277,14 @@ public: if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) { // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum + if (doxygen && doxygenTranslator->hasDocumentation(n)) { + String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0); + if (comment_creation_chatter) + Printf(enum_code, "/* This was generated from enumDeclaration() */\n"); + Printv(enum_code, Char(doxygen_comments), NIL); + Delete(doxygen_comments); + } + String *scope = getCurrentScopeName(nspace); if (!addSymbol(symname, n, scope)) return SWIG_ERROR; @@ -1265,9 +1304,17 @@ public: Replaceall(enum_code, "$static ", ""); Delete(scope); } else { - // Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort if (symname && !Getattr(n, "unnamedinstance")) Printf(constants_code, " // %s \n", symname); + // Translate and write javadoc comment for the enum itself if flagged + if (doxygen && doxygenTranslator->hasDocumentation(n)) { + String *doxygen_comments = doxygenTranslator->getDocumentation(n, " "); + if (comment_creation_chatter) + Printf(constants_code, "/* This was generated from enumDeclaration() */\n"); + Printf(constants_code, Char(doxygen_comments)); + Printf(constants_code, "\n"); + Delete(doxygen_comments); + } } // Emit each enum item @@ -1418,12 +1465,24 @@ public: } if (!addSymbol(symname, n, scope)) return SWIG_ERROR; + + if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) { + if (!GetFlag(n, "firstenumitem")) + Printf(enum_code, ",\n"); + } + + // Translate and write javadoc comment if flagged + if (doxygen && doxygenTranslator->hasDocumentation(n)) { + String *doxygen_comments = doxygenTranslator->getDocumentation(n, " "); + if (comment_creation_chatter) + Printf(enum_code, "/* This was generated from enumvalueDeclaration() */\n"); + Printv(enum_code, Char(doxygen_comments), NIL); + Delete(doxygen_comments); + } if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) { // Wrap (non-anonymous) C/C++ enum with a proper Java enum // Emit the enum item. - if (!GetFlag(n, "firstenumitem")) - Printf(enum_code, ",\n"); Printf(enum_code, " %s", symname); if (Getattr(n, "enumvalue")) { String *value = enumValue(n); @@ -1497,6 +1556,15 @@ public: String *constants_code = NewString(""); Swig_save("constantWrapper", n, "value", NIL); + // Translate and write javadoc comment if flagged + if (doxygen && doxygenTranslator->hasDocumentation(n)) { + String *doxygen_comments = doxygenTranslator->getDocumentation(n, " "); + if (comment_creation_chatter) + Printf(constants_code, "/* This was generated from constantWrapper() */\n"); + Printv(constants_code, Char(doxygen_comments), NIL); + Delete(doxygen_comments); + } + bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0); const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname; @@ -1612,10 +1680,22 @@ public: * ----------------------------------------------------------------------------- */ virtual int insertDirective(Node *n) { + int ret = SWIG_OK; String *code = Getattr(n, "code"); + String *section = Getattr(n, "section"); Replaceall(code, "$module", module_class_name); Replaceall(code, "$imclassname", imclass_name); - return Language::insertDirective(n); + + if (!ImportMode && (Cmp(section, "proxycode") == 0)) { + if (proxy_class_code) { + Swig_typemap_replace_embedded_typemap(code, n); + int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0; + Printv(proxy_class_code, Char(code) + offset, "\n", NIL); + } + } else { + ret = Language::insertDirective(n); + } + return ret; } /* ----------------------------------------------------------------------------- @@ -1796,7 +1876,7 @@ public: Replaceall(cptr_method_name, ".", "_"); Replaceall(cptr_method_name, "$interfacename", interface_name); - String *upcast_method_name = Swig_name_member(getNSpace(), proxy_class_name, cptr_method_name); + String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name); upcastsCode(smart, upcast_method_name, c_classname, c_baseclass); Delete(upcast_method_name); Delete(cptr_method_name); @@ -1924,13 +2004,24 @@ public: // Pure Java interfaces const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE); + if (*Char(interface_list) && *Char(pure_interfaces)) Append(interface_list, ", "); Append(interface_list, pure_interfaces); // Start writing the proxy class if (!has_outerclass) // Import statements Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE),"\n", NIL); - else + + // Translate and write javadoc comment if flagged + if (doxygen && doxygenTranslator->hasDocumentation(n)) { + String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0); + if (comment_creation_chatter) + Printf(proxy_class_def, "/* This was generated from emitProxyClassDefAndCPPCasts() */\n"); + Printv(proxy_class_def, Char(doxygen_comments), NIL); + Delete(doxygen_comments); + } + + if (has_outerclass) Printv(proxy_class_def, "static ", NIL); // C++ nested classes correspond to static java classes Printv(proxy_class_def, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers " $javaclassname", // Class name and bases @@ -1944,16 +2035,19 @@ public: String *destruct = NewString(""); const String *tm = NULL; attributes = NewHash(); - String *destruct_methodname = NULL; - String *destruct_methodmodifiers = NULL; + const String *destruct_methodname = NULL; + const String *destruct_methodmodifiers = NULL; + const String *destruct_parameters = NULL; if (derived) { tm = typemapLookup(n, "javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes); destruct_methodname = Getattr(attributes, "tmap:javadestruct_derived:methodname"); destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct_derived:methodmodifiers"); + destruct_parameters = Getattr(attributes, "tmap:javadestruct_derived:parameters"); } else { tm = typemapLookup(n, "javadestruct", typemap_lookup_type, WARN_NONE, attributes); destruct_methodname = Getattr(attributes, "tmap:javadestruct:methodname"); destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct:methodmodifiers"); + destruct_parameters = Getattr(attributes, "tmap:javadestruct:parameters"); } if (tm && *Char(tm)) { if (!destruct_methodname) { @@ -1962,6 +2056,8 @@ public: if (!destruct_methodmodifiers) { Swig_error(Getfile(n), Getline(n), "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name); } + if (!destruct_parameters) + destruct_parameters = empty_string; } // Emit the finalize and delete methods if (tm) { @@ -1975,8 +2071,15 @@ public: Replaceall(destruct, "$jnicall", destructor_call); else Replaceall(destruct, "$jnicall", "throw new UnsupportedOperationException(\"C++ destructor does not have public access\")"); - if (*Char(destruct)) - Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " void ", destruct_methodname, "()", destructor_throws_clause, " ", destruct, "\n", NIL); + if (*Char(destruct)) { + Printv(proxy_class_def, "\n ", NIL); + const String *methodmods = Getattr(n, "destructmethodmodifiers"); + if (methodmods) + Printv(proxy_class_def, methodmods, NIL); + else + Printv(proxy_class_def, destruct_methodmodifiers, NIL); + Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ")", destructor_throws_clause, " ", destruct, "\n", NIL); + } } if (*Char(interface_upcasts)) Printv(proxy_class_def, interface_upcasts, NIL); @@ -2260,39 +2363,6 @@ public: --nesting_depth; } - /* Output the downcast method, if necessary. Note: There's no other really - good place to put this code, since Abstract Base Classes (ABCs) can and should have - downcasts, making the constructorHandler() a bad place (because ABCs don't get to - have constructors emitted.) */ - if (GetFlag(n, "feature:javadowncast")) { - String *downcast_method = Swig_name_member(getNSpace(), getClassPrefix(), "SWIGDowncast"); - String *jniname = makeValidJniName(downcast_method); - String *wname = Swig_name_wrapper(jniname); - - String *norm_name = SwigType_namestr(Getattr(n, "name")); - - Printf(imclass_class_code, " public final static native %s %s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, downcast_method); - - Wrapper *dcast_wrap = NewWrapper(); - - Printf(dcast_wrap->def, "SWIGEXPORT jobject JNICALL %s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {", wname); - Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n"); - Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n"); - Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name); - Printf(dcast_wrap->code, " if (obj) director = dynamic_cast(obj);\n"); - Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n"); - Printf(dcast_wrap->code, " return jresult;\n"); - Printf(dcast_wrap->code, "}\n"); - - Wrapper_print(dcast_wrap, f_wrappers); - DelWrapper(dcast_wrap); - - Delete(norm_name); - Delete(wname); - Delete(jniname); - Delete(downcast_method); - } - if (f_interface) { Printv(f_interface, interface_class_code, "}\n", NIL); Delete(f_interface); @@ -2438,6 +2508,15 @@ public: setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) == 0); } + // Translate and write javadoc comment if flagged + if (doxygen && doxygenTranslator->hasDocumentation(n)) { + String *doxygen_comments = doxygenTranslator->getDocumentation(n, " "); + if (comment_creation_chatter) + Printf(function_code, "/* This was generated from proxyclassfunctionhandler() */\n"); + Printv(function_code, Char(doxygen_comments), NIL); + Delete(doxygen_comments); + } + /* Start generating the proxy function */ const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); @@ -2445,7 +2524,7 @@ public: if (static_flag) Printf(function_code, "static "); Printf(function_code, "%s %s(", return_type, proxy_function_name); - + if (is_interface) Printf(interface_class_code, " %s %s(", return_type, proxy_function_name); @@ -2565,8 +2644,6 @@ public: Printf(imcall, ")"); Printf(function_code, ")"); - if (is_interface) - Printf(interface_class_code, ");\n"); // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class) if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) { @@ -2624,8 +2701,13 @@ public: Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0)); } + if (is_interface) { + Printf(interface_class_code, ")"); + generateThrowsClause(n, interface_class_code); + Printf(interface_class_code, ";\n"); + } generateThrowsClause(n, function_code); - Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string); + Printf(function_code, " %s\n\n", tm ? tm : empty_string); Printv(proxy_class_code, function_code, NIL); Delete(pre_code); @@ -2670,6 +2752,15 @@ public: tm = Getattr(n, "tmap:jtype"); // typemaps were attached earlier to the node Printf(im_return_type, "%s", tm); + // Translate and write javadoc comment if flagged + if (doxygen && doxygenTranslator->hasDocumentation(n)) { + String *doxygen_comments = doxygenTranslator->getDocumentation(n, " "); + if (comment_creation_chatter) + Printf(function_code, "/* This was generated from constructionhandler() */\n"); + Printv(function_code, Char(doxygen_comments), NIL); + Delete(doxygen_comments); + } + Printf(function_code, " %s %s(", methodmods, proxy_class_name); Printf(helper_code, " static private %s SwigConstruct%s(", im_return_type, proxy_class_name); @@ -2778,7 +2869,8 @@ public: /* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */ Hash *attributes = NewHash(); - String *construct_tm = Copy(typemapLookup(n, "javaconstruct", Getattr(n, "name"), + String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj"); + String *construct_tm = Copy(typemapLookup(n, "javaconstruct", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes)); if (construct_tm) { if (!feature_director) { @@ -2848,6 +2940,9 @@ public: if (proxy_flag) { Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL); generateThrowsClause(n, destructor_throws_clause); + const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); + if (methodmods) + Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods); } return SWIG_OK; } @@ -2931,6 +3026,15 @@ public: String *pre_code = NewString(""); String *post_code = NewString(""); + // Translate and write javadoc comment if flagged + if (doxygen && doxygenTranslator->hasDocumentation(n)) { + String *doxygen_comments = doxygenTranslator->getDocumentation(n, " "); + if (comment_creation_chatter) + Printf(function_code, "/* This was generated from moduleClassFunctionHandler() */\n"); + Printv(function_code, doxygen_comments, NIL); + Delete(doxygen_comments); + } + if (l) { if (SwigType_type(Getattr(l, "type")) == T_VOID) { l = nextSibling(l); @@ -3083,7 +3187,7 @@ public: } generateThrowsClause(n, function_code); - Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string); + Printf(function_code, " %s\n\n", tm ? tm : empty_string); Printv(module_class_code, function_code, NIL); Delete(pre_code); @@ -3748,18 +3852,16 @@ public: Printf(code_wrap->code, " (void)jcls;\n"); Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n"); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); } else { Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name); Printf(code_wrap->code, " (void)jcls;\n"); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName); } - Printf(code_wrap->code, " if (director) {\n"); - Printf(code_wrap->code, " director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), " + Printf(code_wrap->code, " director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), " "(jswig_mem_own == JNI_TRUE), (jweak_global == JNI_TRUE));\n"); - Printf(code_wrap->code, " }\n"); Printf(code_wrap->code, "}\n"); Wrapper_print(code_wrap, f_wrappers); @@ -3778,8 +3880,17 @@ public: Printf(code_wrap->def, "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n", jnipackage, jni_imclass_name, changeown_jnimethod_name); - Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); + + if (Len(smartptr)) { + Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr); + Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); + Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n"); + Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); + } else { + Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name); + Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); + } + Printf(code_wrap->code, " (void)jcls;\n"); Printf(code_wrap->code, " if (director) {\n"); Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n"); @@ -3960,15 +4071,17 @@ public: /* If returning a reference, initialize the pointer to a sane default - if a Java exception occurs, then the pointer returns something other than a NULL-initialized reference. */ - String *non_ref_type = Copy(returntype); + SwigType *noref_type = SwigType_del_reference(Copy(returntype)); + String *noref_ltype = SwigType_lstr(noref_type, 0); + String *return_ltype = SwigType_lstr(returntype, 0); - /* Remove reference and const qualifiers */ - Replaceall(non_ref_type, "r.", ""); - Replaceall(non_ref_type, "q(const).", ""); - Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL); - Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL); - - Delete(non_ref_type); + Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL); + Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL); + Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype); + Printf(w->code, "c_result = &result_default;\n"); + Delete(return_ltype); + Delete(noref_ltype); + Delete(noref_type); } Delete(base_typename); @@ -4059,7 +4172,7 @@ public: Swig_typemap_attach_parms("out", l, 0); Swig_typemap_attach_parms("jni", l, 0); Swig_typemap_attach_parms("jtype", l, 0); - Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorin", l, w); Swig_typemap_attach_parms("javadirectorin", l, 0); Swig_typemap_attach_parms("directorargout", l, w); @@ -4258,11 +4371,11 @@ public: /* header declaration, start wrapper definition */ String *target; SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); - target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); + target = Swig_method_decl(rtype, decl, qualified_name, l, 0); Printf(w->def, "%s", target); Delete(qualified_name); Delete(target); - target = Swig_method_decl(rtype, decl, name, l, 0, 1); + target = Swig_method_decl(rtype, decl, name, l, 1); Printf(declaration, " virtual %s", target); Delete(target); @@ -4281,6 +4394,10 @@ public: } } + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { int gencomma = 0; @@ -4387,7 +4504,7 @@ public: for (p = l; p;) { if ((tm = Getattr(p, "tmap:directorargout"))) { addThrows(n, "tmap:directorargout", p); - Replaceall(tm, "$result", "jresult"); + Replaceall(tm, "$result", makeParameterName(n, p, i, false)); Replaceall(tm, "$input", Getattr(p, "emit:directorinput")); Printv(w->code, tm, "\n", NIL); p = Getattr(p, "tmap:directorargout:next"); @@ -4472,9 +4589,9 @@ public: if (!directorexcept) { directorexcept = NewString(""); Printf(directorexcept, "jthrowable $error = jenv->ExceptionOccurred();\n"); - Printf(directorexcept, "if ($error) {\n"); - Printf(directorexcept, " jenv->ExceptionClear();$directorthrowshandlers\n"); - Printf(directorexcept, " throw Swig::DirectorException(jenv, $error);\n"); + Printf(directorexcept, "if ($error) {"); + Printf(directorexcept, "$directorthrowshandlers\n"); + Printf(directorexcept, " Swig::DirectorException::raise(jenv, $error);\n"); Printf(directorexcept, "}\n"); } else { directorexcept = Copy(directorexcept); @@ -4573,7 +4690,7 @@ public: /* constructor */ { String *basetype = Getattr(parent, "classtype"); - String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 0); + String *target = Swig_method_decl(0, decl, dirclassname, parms, 0); String *call = Swig_csuperclass_call(0, basetype, superparms); String *classtype = SwigType_namestr(Getattr(n, "name")); @@ -4587,7 +4704,7 @@ public: /* constructor header */ { - String *target = Swig_method_decl(0, decl, dirclassname, parms, 0, 1); + String *target = Swig_method_decl(0, decl, dirclassname, parms, 1); Printf(f_directors_h, " %s;\n", target); Delete(target); } @@ -4659,9 +4776,12 @@ public: String *dirClassName = directorClassName(current_class); Wrapper *w = NewWrapper(); - if (Getattr(n, "throw")) { - Printf(f_directors_h, " virtual ~%s() throw ();\n", dirClassName); - Printf(w->def, "%s::~%s() throw () {\n", dirClassName, dirClassName); + if (Getattr(n, "noexcept")) { + Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirClassName); + Printf(w->def, "%s::~%s() noexcept {\n", dirClassName, dirClassName); + } else if (Getattr(n, "throw")) { + Printf(f_directors_h, " virtual ~%s() throw();\n", dirClassName); + Printf(w->def, "%s::~%s() throw() {\n", dirClassName, dirClassName); } else { Printf(f_directors_h, " virtual ~%s();\n", dirClassName); Printf(w->def, "%s::~%s() {\n", dirClassName, dirClassName); @@ -4864,6 +4984,9 @@ extern "C" Language *swig_java(void) { const char *JAVA::usage = "\ Java Options (available with -java)\n\ + -doxygen - Convert C++ doxygen comments to JavaDoc comments in proxy classes\n\ + -debug-doxygen-parser - Display doxygen parser module debugging information\n\ + -debug-doxygen-translator - Display doxygen translator module debugging information\n\ -nopgcpp - Suppress premature garbage collection prevention parameter\n\ -noproxy - Generate the low-level functional interface instead\n\ of proxy classes\n\ diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx index 6f0fb3afd..8c87330b7 100644 --- a/Source/Modules/javascript.cxx +++ b/Source/Modules/javascript.cxx @@ -33,6 +33,7 @@ static bool js_template_enable_debug = false; #define GETTER "getter" #define SETTER "setter" #define PARENT "parent" +#define PARENT_MANGLED "parent_mangled" #define CTOR "ctor" #define CTOR_WRAPPERS "ctor_wrappers" #define CTOR_DISPATCHERS "ctor_dispatchers" @@ -262,7 +263,7 @@ protected: virtual int createNamespace(String *scope); - virtual Hash *createNamespaceEntry(const char *name, const char *parent); + virtual Hash *createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled); virtual int emitNamespaces() = 0; @@ -462,10 +463,10 @@ int JAVASCRIPT::fragmentDirective(Node *n) { // and register them at the emitter. String *section = Getattr(n, "section"); - if (Equal(section, "templates")) { + if (Equal(section, "templates") && !ImportMode) { emitter->registerTemplate(Getattr(n, "value"), Getattr(n, "code")); } else { - Swig_fragment_register(n); + return Language::fragmentDirective(n); } return SWIG_OK; @@ -552,7 +553,7 @@ void JAVASCRIPT::main(int argc, char *argv[]) { emitter = swig_javascript_create_V8Emitter(); Preprocessor_define("SWIG_JAVASCRIPT_V8 1", 0); SWIG_library_directory("javascript/v8"); - // V8 API is C++, so output must be C++ compatibile even when wrapping C code + // V8 API is C++, so output must be C++ compatible even when wrapping C code if (!cparse_cplusplus) { Swig_cparse_cplusplusout(1); } @@ -664,7 +665,7 @@ int JSEmitter::initialize(Node * /*n */ ) { Delete(namespaces); } namespaces = NewHash(); - Hash *global_namespace = createNamespaceEntry("exports", 0); + Hash *global_namespace = createNamespaceEntry("exports", 0, 0); Setattr(namespaces, "::", global_namespace); current_namespace = global_namespace; @@ -993,7 +994,7 @@ int JSEmitter::emitDtor(Node *n) { Also, there is a problem where destructor_action is always true for me, even when not requesting %extend as above. So this code doesn't actually quite work as I expect. The end result is that the code still works because - destructor_action calls free like the original template. The one caveat is the string in destructor_action casts to char* which is wierd. + destructor_action calls free like the original template. The one caveat is the string in destructor_action casts to char* which is weird. I think there is a deeper underlying SWIG issue because I don't think it should be char*. However, it doesn't really matter for free. Maybe the fix for the destructor_action always true problem is that this is supposed to be embedded in the if(Extend) block above. @@ -1124,7 +1125,7 @@ int JSEmitter::emitConstant(Node *n) { Template t_getter(getTemplate("js_getter")); // call the variable methods as a constants are - // registred in same way + // registered in same way enterVariable(n); state.variable(GETTER, wname); // TODO: why do we need this? @@ -1354,6 +1355,11 @@ void JSEmitter::emitCleanupCode(Node *n, Wrapper *wrapper, ParmList *params) { } } + /* See if there is any return cleanup code */ + if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) { + Printf(wrapper->code, "%s\n", tm); + Delete(tm); + } } int JSEmitter::switchNamespace(Node *n) { @@ -1423,19 +1429,20 @@ int JSEmitter::createNamespace(String *scope) { } assert(parent_namespace != 0); - Hash *new_namespace = createNamespaceEntry(Char(scope), Char(Getattr(parent_namespace, "name"))); + Hash *new_namespace = createNamespaceEntry(Char(scope), Char(Getattr(parent_namespace, "name")), Char(Getattr(parent_namespace, "name_mangled"))); Setattr(namespaces, scope, new_namespace); Delete(parent_scope); return SWIG_OK; } -Hash *JSEmitter::createNamespaceEntry(const char *_name, const char *parent) { +Hash *JSEmitter::createNamespaceEntry(const char *_name, const char *parent, const char *parent_mangled) { Hash *entry = NewHash(); String *name = NewString(_name); Setattr(entry, NAME, Swig_scopename_last(name)); Setattr(entry, NAME_MANGLED, Swig_name_mangle(name)); Setattr(entry, PARENT, NewString(parent)); + Setattr(entry, PARENT_MANGLED, NewString(parent_mangled)); Delete(name); return entry; @@ -1462,7 +1469,7 @@ protected: virtual int enterClass(Node *n); virtual int exitClass(Node *n); virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static); - virtual Hash *createNamespaceEntry(const char *name, const char *parent); + virtual Hash *createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled); virtual int emitNamespaces(); private: @@ -1768,8 +1775,8 @@ int JSCEmitter::exitClass(Node *n) { return SWIG_OK; } -Hash *JSCEmitter::createNamespaceEntry(const char *name, const char *parent) { - Hash *entry = JSEmitter::createNamespaceEntry(name, parent); +Hash *JSCEmitter::createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled) { + Hash *entry = JSEmitter::createNamespaceEntry(name, parent, parent_mangled); Setattr(entry, "functions", NewString("")); Setattr(entry, "values", NewString("")); return entry; @@ -1781,8 +1788,7 @@ int JSCEmitter::emitNamespaces() { Hash *entry = it.item; String *name = Getattr(entry, NAME); String *name_mangled = Getattr(entry, NAME_MANGLED); - String *parent = Getattr(entry, PARENT); - String *parent_mangled = Swig_name_mangle(parent); + String *parent_mangled = Getattr(entry, PARENT_MANGLED); String *functions = Getattr(entry, "functions"); String *variables = Getattr(entry, "values"); @@ -2032,7 +2038,7 @@ int V8Emitter::exitClass(Node *n) { .pretty_print(f_init_inheritance); Delete(base_name_mangled); } - // emit registeration of class template + // emit registration of class template Template t_register = getTemplate("jsv8_register_class"); t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED)) .replace("$jsname", state.clazz(NAME)) @@ -2201,7 +2207,7 @@ int V8Emitter::emitNamespaces() { String *name = Getattr(entry, NAME); String *name_mangled = Getattr(entry, NAME_MANGLED); String *parent = Getattr(entry, PARENT); - String *parent_mangled = Swig_name_mangle(parent); + String *parent_mangled = Getattr(entry, PARENT_MANGLED); bool do_create = true; bool do_register = true; @@ -2422,7 +2428,7 @@ Template & Template::trim() { /* ----------------------------------------------------------------------------- * Template& Template::replace(const String* pattern, const String* repl) : * - * replaces all occurences of a given pattern with a given replacement. + * replaces all occurrences of a given pattern with a given replacement. * * - pattern: the pattern to be replaced * - repl: the replacement string diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 9b1173443..f7979b611 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -81,7 +81,6 @@ extern int AddExtern; /* import modes */ #define IMPORT_MODE 1 -#define IMPORT_MODULE 2 /* ---------------------------------------------------------------------- * Dispatcher::emit_one() @@ -308,15 +307,12 @@ int Dispatcher::namespaceDeclaration(Node *n) { return defaultHandler(n); } - /* Allocators */ Language::Language(): none_comparison(NewString("$arg != 0")), director_ctor_code(NewString("")), director_prot_ctor_code(0), symtabs(NewHash()), -classtypes(NewHash()), -enumtypes(NewHash()), overloading(0), multiinput(0), cplus_runtime(0), @@ -337,12 +333,12 @@ directors(0) { director_language = 0; assert(!this_); this_ = this; + + doxygenTranslator = NULL; } Language::~Language() { Delete(symtabs); - Delete(classtypes); - Delete(enumtypes); Delete(director_ctor_code); Delete(none_comparison); this_ = 0; @@ -625,7 +621,8 @@ int Language::constantDirective(Node *n) { * ---------------------------------------------------------------------- */ int Language::fragmentDirective(Node *n) { - Swig_fragment_register(n); + if (!(Getattr(n, "emitonly") && ImportMode)) + Swig_fragment_register(n); return SWIG_OK; } @@ -870,7 +867,7 @@ int Language::cDeclaration(Node *n) { } else { // Found an unignored templated method that has an empty template instantiation (%template()) // Ignore it unless it has been %rename'd - if (Strncmp(symname, "__dummy_", 8) == 0) { + if (Strncmp(symname, "__dummy_", 8) == 0 && Cmp(storage, "typedef") != 0) { SetFlag(n, "feature:ignore"); Swig_warning(WARN_LANG_TEMPLATE_METHOD_IGNORE, input_file, line_number, "%%template() contains no name. Template method ignored: %s\n", Swig_name_decl(n)); @@ -1084,6 +1081,8 @@ int Language::functionHandler(Node *n) { globalfunctionHandler(n); InClass = oldInClass; } else { + // This is a member function, set a flag so the documentation type is correct + SetFlag(n, "memberfunction"); Node *explicit_n = 0; if (directorsEnabled() && is_member_director(CurrentClass, n) && !extraDirectorProtectedCPPMethodsRequired()) { bool virtual_but_not_pure_virtual = (!(Cmp(storage, "virtual")) && (Cmp(Getattr(n, "value"), "0") != 0)); @@ -1145,7 +1144,9 @@ int Language::globalfunctionHandler(Node *n) { Delete(cbname); } Setattr(n, "parms", nonvoid_parms(parms)); - String *call = Swig_cfunction_call(name, parms); + + String *extendname = Getattr(n, "extendname"); + String *call = Swig_cfunction_call(extendname ? extendname : name, parms); String *cres = Swig_cresult(type, Swig_cresult_name(), call); Setattr(n, "wrap:action", cres); Delete(cres); @@ -1267,9 +1268,13 @@ int Language::memberfunctionHandler(Node *n) { if (GetFlag(n, "explicitcall")) DirectorExtraCall = CWRAP_DIRECTOR_ONE_CALL; - Swig_MethodToFunction(n, NSpace, ClassType, Getattr(n, "template") ? SmartPointer : Extend | SmartPointer | DirectorExtraCall, director_type, - is_member_director(CurrentClass, n)); + int extendmember = GetFlag(n, "isextendmember") ? Extend : 0; + int flags = Getattr(n, "template") ? extendmember | SmartPointer : Extend | SmartPointer | DirectorExtraCall; + Swig_MethodToFunction(n, NSpace, ClassType, flags, director_type, is_member_director(CurrentClass, n)); Setattr(n, "sym:name", fname); + /* Explicitly save low-level and high-level documentation names */ + Setattr(n, "doc:low:name", fname); + Setattr(n, "doc:high:name", symname); functionWrapper(n); @@ -1321,12 +1326,18 @@ int Language::staticmemberfunctionHandler(Node *n) { if (!defaultargs && code) { /* Hmmm. An added static member. We have to create a little wrapper for this */ - Swig_add_extension_code(n, cname, parms, type, code, CPlusPlus, 0); + String *mangled_cname = Swig_name_mangle(cname); + Swig_add_extension_code(n, mangled_cname, parms, type, code, CPlusPlus, 0); + Setattr(n, "extendname", mangled_cname); + Delete(mangled_cname); } } Setattr(n, "name", cname); Setattr(n, "sym:name", mrename); + /* Explicitly save low-level and high-level documentation names */ + Setattr(n, "doc:low:name", mrename); + Setattr(n, "doc:high:name", symname); if (cb) { String *cbname = NewStringf(cb, symname); @@ -1883,6 +1894,8 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_ } if (!checkAttribute(nn, "storage", "virtual")) continue; + if (GetFlag(nn, "final")) + continue; /* we need to add methods(cdecl) and destructor (to check for throw decl) */ int is_destructor = (Cmp(nodeType, "destructor") == 0); if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) { @@ -1943,7 +1956,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_ generation of 'empty' director classes. But this has to be done outside the previous 'for' - an the recursive loop!. + and the recursive loop!. */ if (n == parent) { int len = Len(vm); @@ -2072,7 +2085,7 @@ int Language::classDirectorConstructors(Node *n) { needed, since there is a public constructor already defined. (scottm) This code is needed here to make the director_abstract + - test generate compilable code (Example2 in director_abastract.i). + test generate compilable code (Example2 in director_abstract.i). (mmatus) This is very strange, since swig compiled with gcc3.2.3 doesn't need it here.... @@ -2098,7 +2111,7 @@ int Language::classDirectorMethods(Node *n) { Node *item = Getitem(vtable, i); String *method = Getattr(item, "methodNode"); String *fqdname = Getattr(item, "fqdname"); - if (GetFlag(method, "feature:nodirector")) + if (GetFlag(method, "feature:nodirector") || GetFlag(method, "final")) continue; String *wrn = Getattr(method, "feature:warnfilter"); @@ -2145,8 +2158,8 @@ int Language::classDirectorDestructor(Node *n) { File *f_directors = Swig_filebyname("director"); File *f_directors_h = Swig_filebyname("director_h"); if (Getattr(n, "throw")) { - Printf(f_directors_h, " virtual ~%s() throw ();\n", DirectorClassName); - Printf(f_directors, "%s::~%s() throw () {\n}\n\n", DirectorClassName, DirectorClassName); + Printf(f_directors_h, " virtual ~%s() throw();\n", DirectorClassName); + Printf(f_directors, "%s::~%s() throw() {\n}\n\n", DirectorClassName, DirectorClassName); } else { Printf(f_directors_h, " virtual ~%s();\n", DirectorClassName); Printf(f_directors, "%s::~%s() {\n}\n\n", DirectorClassName, DirectorClassName); @@ -2187,6 +2200,16 @@ int Language::classDirector(Node *n) { String *using_protected_members_code = NewString(""); for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) { Node *nodeType = Getattr(ni, "nodeType"); + if (Cmp(nodeType, "destructor") == 0 && GetFlag(ni, "final")) { + String *classtype = Getattr(n, "classtype"); + SWIG_WARN_NODE_BEGIN(ni); + Swig_warning(WARN_LANG_DIRECTOR_FINAL, input_file, line_number, "Destructor %s is final, %s cannot be a director class.\n", Swig_name_decl(ni), classtype); + SWIG_WARN_NODE_END(ni); + SetFlag(n, "feature:nodirector"); + Delete(vtable); + Delete(using_protected_members_code); + return SWIG_OK; + } bool cdeclaration = (Cmp(nodeType, "cdecl") == 0); if (cdeclaration && !GetFlag(ni, "feature:ignore")) { if (isNonVirtualProtectedAccess(ni)) { @@ -2785,7 +2808,9 @@ int Language::constructorHandler(Node *n) { Setattr(n, "handled_as_constructor", "1"); } - Swig_ConstructorToFunction(n, NSpace, ClassType, none_comparison, director_ctor, CPlusPlus, Getattr(n, "template") ? 0 : Extend, DirectorClassName); + int extendmember = GetFlag(n, "isextendmember") ? Extend : 0; + int flags = Getattr(n, "template") ? extendmember : Extend; + Swig_ConstructorToFunction(n, NSpace, ClassType, none_comparison, director_ctor, CPlusPlus, flags, DirectorClassName); Setattr(n, "sym:name", mrename); functionWrapper(n); Delete(mrename); @@ -3256,11 +3281,13 @@ Node *Language::symbolLookup(const String *s, const_String_or_char_ptr scope) { * Tries to locate a class from a type definition * ----------------------------------------------------------------------------- */ -Node *Language::classLookup(const SwigType *s) const { +Node *Language::classLookup(const SwigType *s) { + static Hash *classtypes = 0; + Node *n = 0; /* Look in hash of cached values */ - n = Getattr(classtypes, s); + n = classtypes ? Getattr(classtypes, s) : 0; if (!n) { Symtab *stab = 0; SwigType *ty1 = SwigType_typedef_resolve_all(s); @@ -3288,6 +3315,14 @@ Node *Language::classLookup(const SwigType *s) const { break; if (Strcmp(nodeType(n), "class") == 0) break; + Node *sibling = n; + while (sibling) { + sibling = Getattr(sibling, "csym:nextSibling"); + if (sibling && Strcmp(nodeType(sibling), "class") == 0) + break; + } + if (sibling) + break; n = parentNode(n); if (!n) break; @@ -3300,7 +3335,7 @@ Node *Language::classLookup(const SwigType *s) const { } if (n) { /* Found a match. Look at the prefix. We only allow - the cases where where we want a proxy class for the particular type */ + the cases where we want a proxy class for the particular type */ bool acceptable_prefix = (Len(prefix) == 0) || // simple type (pass by value) (Strcmp(prefix, "p.") == 0) || // pointer @@ -3315,6 +3350,8 @@ Node *Language::classLookup(const SwigType *s) const { } if (acceptable_prefix) { SwigType *cs = Copy(s); + if (!classtypes) + classtypes = NewHash(); Setattr(classtypes, cs, n); Delete(cs); } else { @@ -3341,10 +3378,12 @@ Node *Language::classLookup(const SwigType *s) const { * ----------------------------------------------------------------------------- */ Node *Language::enumLookup(SwigType *s) { + static Hash *enumtypes = 0; + Node *n = 0; /* Look in hash of cached values */ - n = Getattr(enumtypes, s); + n = enumtypes ? Getattr(enumtypes, s) : 0; if (!n) { Symtab *stab = 0; SwigType *lt = SwigType_ltype(s); @@ -3385,6 +3424,8 @@ Node *Language::enumLookup(SwigType *s) { if (n) { /* Found a match. Look at the prefix. We only allow simple types. */ if (Len(prefix) == 0) { /* Simple type */ + if (!enumtypes) + enumtypes = NewHash(); Setattr(enumtypes, Copy(s), n); } else { n = 0; @@ -3505,7 +3546,7 @@ int Language::need_nonpublic_ctor(Node *n) { Note: given all the complications here, I am always in favor to always enable 'dirprot', since is the C++ idea of protected - members, and use %ignore for the method you don't whan to add in + members, and use %ignore for the method you don't want to add in the director class. */ if (directorsEnabled()) { @@ -3581,7 +3622,7 @@ String *Language::makeParameterName(Node *n, Parm *p, int arg_num, bool setter) String *arg = 0; String *pn = Getattr(p, "name"); - // Use C parameter name unless it is a duplicate or an empty parameter name + // Check if parameter name is a duplicate. int count = 0; ParmList *plist = Getattr(n, "parms"); while (plist) { @@ -3589,8 +3630,14 @@ String *Language::makeParameterName(Node *n, Parm *p, int arg_num, bool setter) count++; plist = nextSibling(plist); } - String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0; - arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn); + + // If the parameter has no name at all or has a non-unique name, replace it with "argN". + if (!pn || count > 1) { + arg = NewStringf("arg%d", arg_num); + } else { + // Otherwise, try to use the original C name, but modify it if necessary to avoid conflicting with the language keywords. + arg = Swig_name_make(p, 0, pn, 0, 0); + } if (setter && Cmp(arg, "self") != 0) { // Some languages (C#) insist on calling the input variable "value" while @@ -3765,7 +3812,7 @@ int Language::abstractClassTest(Node *n) { if (dirabstract) { if (is_public(dirabstract)) { Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT, Getfile(n), Getline(n), - "Director class '%s' is abstract, abstract method '%s' is not accesible, maybe due to multiple inheritance or 'nodirector' feature\n", + "Director class '%s' is abstract, abstract method '%s' is not accessible, maybe due to multiple inheritance or 'nodirector' feature\n", SwigType_namestr(Getattr(n, "name")), Getattr(dirabstract, "name")); } else { Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT, Getfile(n), Getline(n), diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx index 80ea47f3f..188b11c2b 100644 --- a/Source/Modules/lua.cxx +++ b/Source/Modules/lua.cxx @@ -141,7 +141,7 @@ private: // This variable holds the name of the current class in Lua. Usually it is // the same as C++ class name, but rename directives can change it. String *proxy_class_name; - // This is a so calld fully qualified symname - the above proxy class name + // This is a so called fully qualified symname - the above proxy class name // prepended with class namespace. If class Lua name is the same as class C++ name, // then it is basically C++ fully qualified name with colons replaced with dots. String *full_proxy_class_name; @@ -1359,7 +1359,7 @@ public: String *rt = Copy(getClassType()); SwigType_add_pointer(rt); - // Adding class to apropriate namespace + // Adding class to appropriate namespace registerClass(nspace, wrap_class_name); Hash *nspaceHash = getCArraysHash(nspace); @@ -1461,7 +1461,7 @@ public: assert(proxy_class_name); assert(full_proxy_class_name); - // Then print class isntance part + // Then print class instance part Printv(f_wrappers, "static swig_lua_class *swig_", mangled_full_proxy_class_name, "_bases[] = {", base_class, "0};\n", NIL); Delete(base_class); Printv(f_wrappers, "static const char *swig_", mangled_full_proxy_class_name, "_base_names[] = {", base_class_names, "0};\n", NIL); @@ -1755,7 +1755,7 @@ public: * * This is to convert the string of Lua code into a proper string, which can then be * emitted into the C/C++ code. - * Basically is is a lot of search & replacing of odd sequences + * Basically it is a lot of search & replacing of odd sequences * ---------------------------------------------------------------------------- */ void escapeCode(String *str) { @@ -1770,7 +1770,7 @@ public: /* ----------------------------------------------------------------------------- * rawGetCArraysHash(String *name) * - * A small helper to hide impelementation of how CArrays hashes are stored + * A small helper to hide implementation of how CArrays hashes are stored * ---------------------------------------------------------------------------- */ Hash *rawGetCArraysHash(const_String_or_char_ptr name) { @@ -2110,7 +2110,7 @@ public: // variable in resulting file getCArraysHash(0); } - // Because we cant access directly 'symtabs', instead we access + // Because we can't directly access 'symtabs', instead we access // top-level scope and look on all scope pseudo-symbols in it. Hash *top_scope = symbolScopeLookup(""); assert(top_scope); @@ -2193,7 +2193,7 @@ public: String *luaCurrentSymbolNSpace() { String *scope = 0; - // If ouside class, than NSpace is used. + // If outside class, than NSpace is used. // If inside class, but current[NO_CPP], then this is friend function. It belongs to NSpace if (!getCurrentClass() || current[NO_CPP]) { scope = getNSpace(); diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 632a001ac..c6bd148e2 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -38,14 +38,15 @@ int NoExcept = 0; int SwigRuntime = 0; // 0 = no option, 1 = -runtime, 2 = -noruntime /* Suppress warning messages for private inheritance, preprocessor evaluation etc... - WARN_PP_EVALUATION 202 - WARN_PARSE_PRIVATE_INHERIT 309 - WARN_TYPE_ABSTRACT 403 - WARN_LANG_OVERLOAD_CONST 512 - WARN_PARSE_BUILTIN_NAME 321 - WARN_PARSE_REDUNDANT 322 + WARN_PP_EVALUATION 202 + WARN_PARSE_PRIVATE_INHERIT 309 + WARN_PARSE_BUILTIN_NAME 321 + WARN_PARSE_REDUNDANT 322 + WARN_TYPE_ABSTRACT 403 + WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405 + WARN_LANG_OVERLOAD_CONST 512 */ -#define EXTRA_WARNINGS "202,309,403,512,321,322" +#define EXTRA_WARNINGS "202,309,403,405,512,321,322" extern "C" { extern String *ModuleName; @@ -64,7 +65,7 @@ static const char *usage1 = (const char *) "\ -copyctor - Automatically generate copy constructors wherever possible\n\ -cpperraswarn - Treat the preprocessor #error statement as #warning (default)\n\ -cppext - Change file extension of generated C++ files to \n\ - (default is cxx, except for PHP which uses cpp)\n\ + (default is cxx)\n\ -copyright - Display copyright notices\n\ -debug-classes - Display information about the classes found in the interface\n\ -debug-module - Display module parse tree at stages 1-4, is a csv list of stages\n\ @@ -96,7 +97,7 @@ static const char *usage2 = (const char *) "\ -Fmicrosoft - Display error/warning messages in Microsoft format\n\ -Fstandard - Display error/warning messages in commonly used format\n\ -fvirtual - Compile in virtual elimination mode\n\ - -help - This output\n\ + -help - Display help\n\ -I- - Don't search the current directory\n\ -I

      - Look for SWIG files in directory \n\ -ignoremissing - Ignore missing include files\n\ @@ -129,14 +130,14 @@ static const char *usage3 = (const char *) "\ "; static const char *usage4 = (const char *) "\ - -O - Enable the optimization options: \n\ - -fastdispatch -fvirtual \n\ + -O - Enable the optimization options:\n\ + -fastdispatch -fvirtual\n\ -o - Set name of C/C++ output file to \n\ -oh - Set name of C++ output header file for directors to \n\ -outcurrentdir - Set default output dir to current dir instead of input file's path\n\ -outdir - Set language specific files output directory to \n\ -pcreversion - Display PCRE version information\n\ - -small - Compile in virtual elimination & compact mode\n\ + -small - Compile in virtual elimination and compact mode\n\ -swiglib - Report location of SWIG library and exit\n\ -templatereduce - Reduce all the typedefs in templates\n\ -v - Run in verbose mode\n\ @@ -154,10 +155,14 @@ Options can also be defined using the SWIG_FEATURES environment variable, for ex $ export SWIG_FEATURES\n\ $ swig -python interface.i\n\ \n\ -is equivalent to: \n\ +is equivalent to:\n\ \n\ - $ swig -Wall -python interface.i \n\ + $ swig -Wall -python interface.i\n\ \n\ +Arguments may also be passed in a file, separated by whitespace. For example:\n\ +\n\ + $ echo \"-Wall -python interface.i\" > args.txt\n\ + $ swig @args.txt\n\ \n"; // Local variables @@ -454,7 +459,7 @@ static void SWIG_dump_runtime() { SWIG_exit(EXIT_SUCCESS); } -void SWIG_getoptions(int argc, char *argv[]) { +static void getoptions(int argc, char *argv[]) { int i; // Get options for (i = 1; i < argc; i++) { @@ -873,7 +878,7 @@ void SWIG_getoptions(int argc, char *argv[]) { } } -int SWIG_main(int argc, char *argv[], Language *l) { +int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm) { char *c; /* Initialize the SWIG core */ @@ -885,7 +890,9 @@ int SWIG_main(int argc, char *argv[], Language *l) { // Initialize the preprocessor Preprocessor_init(); - lang = l; + // Set lang to a dummy value if no target language was specified so we + // can process options enough to handle -version, etc. + lang = tlm ? tlm->fac() : new Language; // Set up some default symbols (available in both SWIG interface files // and C files) @@ -918,9 +925,9 @@ int SWIG_main(int argc, char *argv[], Language *l) { Wrapper_director_protected_mode_set(1); // Inform the parser if the nested classes should be ignored unless explicitly told otherwise via feature:flatnested - ignore_nested_classes = l->nestedClassesSupport() == Language::NCS_Unknown ? 1 : 0; + ignore_nested_classes = lang->nestedClassesSupport() == Language::NCS_Unknown ? 1 : 0; - kwargs_supported = l->kwargsSupport() ? 1 : 0; + kwargs_supported = lang->kwargsSupport() ? 1 : 0; // Create Library search directories @@ -949,7 +956,7 @@ int SWIG_main(int argc, char *argv[], Language *l) { /* Check for SWIG_FEATURES environment variable */ - SWIG_getoptions(argc, argv); + getoptions(argc, argv); // Define the __cplusplus symbol if (CPlusPlus) @@ -962,6 +969,7 @@ int SWIG_main(int argc, char *argv[], Language *l) { Printf(stdout, "\nNote: 'swig - -help' displays options for a specific target language.\n\n"); SWIG_exit(EXIT_SUCCESS); // Exit if we're in help mode } + // Check all of the options to make sure we're cool. // Don't check for an input file if -external-runtime is passed Swig_check_options(external_runtime ? 0 : 1); @@ -1057,7 +1065,7 @@ int SWIG_main(int argc, char *argv[], Language *l) { char *cfile = Char(input_file); if (cfile && cfile[0] == '-') { Printf(stderr, "Unable to find option or file '%s', ", input_file); - Printf(stderr, "use 'swig -help' for more information.\n"); + Printf(stderr, "Use 'swig -help' for more information.\n"); } else { Printf(stderr, "Unable to find file '%s'.\n", input_file); } @@ -1066,6 +1074,13 @@ int SWIG_main(int argc, char *argv[], Language *l) { Swig_warning(WARN_DEPRECATED_INPUT_FILE, "SWIG", 1, "Use of the include path to find the input file is deprecated and will not work with ccache. Please include the path when specifying the input file.\n"); // so that behaviour is like c/c++ compilers } } + + if (!tlm) { + Printf(stderr, "No target language specified.\n"); + Printf(stderr, "Use 'swig -help' for more information.\n"); + SWIG_exit(EXIT_FAILURE); + } + if (!no_cpp) { fclose(df); Printf(fs, "%%include \n"); @@ -1300,6 +1315,13 @@ int SWIG_main(int argc, char *argv[], Language *l) { // Check the extension for a c/c++ file. If so, we're going to declare everything we see as "extern" ForceExtern = check_extension(input_file); + if (tlm->status == Experimental) { + Swig_warning(WARN_LANG_EXPERIMENTAL, "SWIG", 1, "Experimental target language. " + "Target language %s specified by %s is an experimental language. " + "Please read about SWIG experimental languages, http://swig.org/Doc4.0/Introduction.html#Introduction_experimental_status.\n", + tlm->help ? tlm->help : "", tlm->name); + } + lang->top(top); if (browse) { diff --git a/Source/Modules/modula3.cxx b/Source/Modules/modula3.cxx index 9983e69d2..c606845ea 100644 --- a/Source/Modules/modula3.cxx +++ b/Source/Modules/modula3.cxx @@ -219,8 +219,8 @@ private: String *module_baseclass; //inheritance for module class from %pragma String *m3raw_interfaces; //interfaces for intermediary class class from %pragma String *module_interfaces; //interfaces for module class from %pragma - String *m3raw_class_modifiers; //class modifiers for intermediary class overriden by %pragma - String *m3wrap_modifiers; //class modifiers for module class overriden by %pragma + String *m3raw_class_modifiers; //class modifiers for intermediary class overridden by %pragma + String *m3wrap_modifiers; //class modifiers for module class overridden by %pragma String *upcasts_code; //C++ casts for inheritance hierarchies C++ code String *m3raw_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code String *destructor_call; //C++ destructor call if any @@ -822,7 +822,7 @@ MODULA3(): Printf(file, "\n"); Printf(file, "int main (int argc, char *argv[]) {\n"); Printf(file, "\ -/*This progam must work for floating point numbers and integers.\n\ +/*This program must work for floating point numbers and integers.\n\ Thus all numbers are converted to double precision floating point format.*/\n"); scanConstant(file, n); Printf(file, " return 0;\n"); @@ -3214,7 +3214,7 @@ MODULA3(): tm = Getattr(p, "tmap:m3wrapargvar"); if (tm != NIL) { - /* exceptions that may be raised but can't be catched, + /* exceptions that may be raised but can't be caught, thus we won't count them in num_exceptions */ addImports(m3wrap_impl.import, "m3wrapargvar", p); addThrows(throws_hash, "m3wrapargvar", p); diff --git a/Source/Modules/module.cxx b/Source/Modules/module.cxx deleted file mode 100644 index aa48689ab..000000000 --- a/Source/Modules/module.cxx +++ /dev/null @@ -1,59 +0,0 @@ -/* ----------------------------------------------------------------------------- - * This file is part of SWIG, which is licensed as a whole under version 3 - * (or any later version) of the GNU General Public License. Some additional - * terms also apply to certain portions of SWIG. The full details of the SWIG - * license and copyrights can be found in the LICENSE and COPYRIGHT files - * included with the SWIG source code as distributed by the SWIG developers - * and at http://www.swig.org/legal.html. - * - * module.cxx - * - * This file is responsible for the module system. - * ----------------------------------------------------------------------------- */ - -#include "swigmod.h" - -struct Module { - ModuleFactory fac; - char *name; - Module *next; - Module(const char *n, ModuleFactory f) { - fac = f; - name = new char[strlen(n) + 1]; - strcpy(name, n); - next = 0; - } ~Module() { - delete[]name; - } -}; - -static Module *modules = 0; - -/* ----------------------------------------------------------------------------- - * void Swig_register_module() - * - * Register a module. - * ----------------------------------------------------------------------------- */ - -void Swig_register_module(const char *n, ModuleFactory f) { - Module *m = new Module(n, f); - m->next = modules; - modules = m; -} - -/* ----------------------------------------------------------------------------- - * Language *Swig_find_module() - * - * Given a command line option, locates the factory function. - * ----------------------------------------------------------------------------- */ - -ModuleFactory Swig_find_module(const char *name) { - Module *m = modules; - while (m) { - if (strcmp(m->name, name) == 0) { - return m->fac; - } - m = m->next; - } - return 0; -} diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx index dd3aecc40..788681330 100644 --- a/Source/Modules/mzscheme.cxx +++ b/Source/Modules/mzscheme.cxx @@ -17,12 +17,10 @@ static const char *usage = "\ Mzscheme Options (available with -mzscheme)\n\ - -declaremodule - Create extension that declares a module\n\ - -dynamic-load ,[library,...] - Do not link with these libraries, dynamic load\n\ - them\n\ - -noinit - Do not emit scheme_initialize, scheme_reload,\n\ - scheme_module_name functions\n\ - -prefix - Set a prefix to be prepended to all names\n\ + -declaremodule - Create extension that declares a module\n\ + -dynamic-load ,[lib,...] - Do not link with these libraries, dynamic load them\n\ + -noinit - Do not emit module initialization code\n\ + -prefix - Set a prefix to be prepended to all names\n\ "; static String *fieldnames_tab = 0; @@ -223,7 +221,6 @@ public: Wrapper *f = NewWrapper(); String *proc_name = NewString(""); - String *source = NewString(""); String *target = NewString(""); String *arg = NewString(""); String *cleanup = NewString(""); @@ -314,10 +311,9 @@ public: String *ln = Getattr(p, "lname"); // Produce names of source and target - Clear(source); Clear(target); Clear(arg); - Printf(source, "argv[%d]", i); + String *source = NewStringf("argv[%d]", i); Printf(target, "%s", ln); Printv(arg, Getattr(p, "name"), NIL); @@ -341,6 +337,7 @@ public: if (i >= numreq) { Printf(f->code, "}\n"); } + Delete(source); } /* Insert constraint checking code */ @@ -439,9 +436,8 @@ public: sprintf(temp, "%d", numargs); if (exporting_destructor) { Printf(init_func_def, "SWIG_TypeClientData(SWIGTYPE%s, (void *) %s);\n", swigtype_ptr, wname); - } else { - Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", proc_name, wname, proc_name, numreq, numargs); } + Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", proc_name, wname, proc_name, numreq, numargs); } else { if (!Getattr(n, "sym:nextSibling")) { /* Emit overloading dispatch function */ @@ -457,6 +453,7 @@ public: Printv(df->def, "static Scheme_Object *\n", dname, "(int argc, Scheme_Object **argv) {", NIL); Printv(df->code, dispatch, "\n", NIL); Printf(df->code, "scheme_signal_error(\"No matching function for overloaded '%s'\");\n", iname); + Printf(df->code, "return NULL;\n", iname); Printv(df->code, "}\n", NIL); Wrapper_print(df, f_wrappers); Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", proc_name, dname, proc_name, 0, maxargs); @@ -467,7 +464,6 @@ public: } Delete(proc_name); - Delete(source); Delete(target); Delete(arg); Delete(outarg); @@ -528,7 +524,7 @@ public: Replaceall(tm, "$source", "argv[0]"); Replaceall(tm, "$target", name); Replaceall(tm, "$input", "argv[0]"); - /* Printv(f->code, tm, "\n",NIL); */ + Replaceall(tm, "$argnum", "1"); emit_action_code(n, f->code, tm); } else { throw_unhandled_mzscheme_type_error(t); @@ -765,7 +761,7 @@ public: /* ------------------------------------------------------------ - * validIdentifer() + * validIdentifier() * ------------------------------------------------------------ */ virtual int validIdentifier(String *s) { diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx index 9df6a9551..6f2a34962 100644 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -68,7 +68,7 @@ public: director_prot_ctor_code = NewString(""); Printv(director_prot_ctor_code, "if ( $comparison ) { /* subclassed */\n", - " $director_new \n", "} else {\n", " failwith(\"accessing abstract class or protected constructor\"); \n", "}\n", NIL); + " $director_new \n", "} else {\n", " caml_failwith(\"accessing abstract class or protected constructor\"); \n", "}\n", NIL); director_multiple_inheritance = 1; director_language = 1; } @@ -167,6 +167,12 @@ public: return declaration; } + void emitBanner(File *f) { + Printf(f, "(* ----------------------------------------------------------------------------\n"); + Swig_banner_target_lang(f, " *"); + Printf(f, " * ---------------------------------------------------------------------------- *)\n\n"); + } + /* ------------------------------------------------------------ * top() * @@ -196,6 +202,7 @@ public: * use %module(directors="1") modulename at the start of the * interface file to enable director generation. */ + String *mod_docstring = NULL; { Node *module = Getattr(n, "module"); if (module) { @@ -210,6 +217,7 @@ public: if (Getattr(options, "sizeof")) { generate_sizeof = 1; } + mod_docstring = Getattr(options, "docstring"); } } } @@ -310,9 +318,19 @@ public: FileErrorDisplay(mlifilen); SWIG_exit(EXIT_FAILURE); } + emitBanner(f_mlout); + emitBanner(f_mliout); Language::top(n); + if (mod_docstring) { + if (Len(mod_docstring)) { + Printv(f_mliout, "(** ", mod_docstring, " *)\n", NIL); + } + Delete(mod_docstring); + mod_docstring = NULL; + } + Printf(f_enum_to_int, ") | _ -> (C_int (get_int v))\n" "let _ = Callback.register \"%s_enum_to_int\" enum_to_int\n", module); Printf(f_mlibody, "val enum_to_int : c_enum_type -> c_obj -> Swig.c_obj\n"); @@ -417,6 +435,29 @@ public: return SwigType_isarray(SwigType_typedef_resolve_all(t)); } + virtual int membervariableHandler(Node *n) { + String *symname = Getattr(n, "sym:name"); + Language::membervariableHandler(n); + + String *mname = Swig_name_member(NSPACE_TODO, classname, symname); + String *getname = Swig_name_get(NSPACE_TODO, mname); + String *mangled_getname = mangleNameForCaml(getname); + Delete(getname); + + if (!GetFlag(n, "feature:immutable")) { + String *setname = Swig_name_set(NSPACE_TODO, mname); + String *mangled_setname = mangleNameForCaml(setname); + Delete(setname); + Printf(f_class_ctors, " \"[%s]\", (fun args -> " "if args = (C_list [ raw_ptr ]) then _%s args else _%s args) ;\n", symname, mangled_getname, mangled_setname); + Delete(mangled_setname); + } else { + Printf(f_class_ctors, " \"[%s]\", (fun args -> " "if args = (C_list [ raw_ptr ]) then _%s args else C_void) ;\n", symname, mangled_getname); + } + Delete(mangled_getname); + Delete(mname); + return SWIG_OK; + } + /* ------------------------------------------------------------ * functionWrapper() * Create a function declaration and register it with the interpreter. @@ -432,7 +473,6 @@ public: Wrapper *f = NewWrapper(); String *proc_name = NewString(""); - String *source = NewString(""); String *target = NewString(""); String *arg = NewString(""); String *cleanup = NewString(""); @@ -447,6 +487,8 @@ public: int destructor = (!Cmp(nodeType, "destructor")); String *overname = 0; bool isOverloaded = Getattr(n, "sym:overloaded") ? true : false; + // For overloaded functions, only the dispatch function needs to be exposed in the ml and mli files. + bool expose_func = !isOverloaded || !Getattr(n, "sym:nextSibling"); // Make a wrapper name for this String *wname = Swig_name_wrapper(iname); @@ -470,33 +512,19 @@ public: Printv(proc_name, "_", iname, NIL); String *mangled_name = mangleNameForCaml(proc_name); - if (classmode && in_constructor) { // Emit constructor for object + if (classmode && in_constructor && expose_func) { // Emit constructor for object String *mangled_name_nounder = NewString((char *) (Char(mangled_name)) + 1); Printf(f_class_ctors_end, "let %s clst = _%s clst\n", mangled_name_nounder, mangled_name_nounder); Printf(f_mlibody, "val %s : c_obj -> c_obj\n", mangled_name_nounder); Delete(mangled_name_nounder); } else if (classmode && in_destructor) { Printf(f_class_ctors, " \"~\", %s ;\n", mangled_name); - } else if (classmode && !in_constructor && !in_destructor && !static_member_function) { + } else if (classmode && !in_constructor && !in_destructor && !static_member_function && + !Getattr(n, "membervariableHandler:sym:name") && expose_func) { String *opname = Copy(Getattr(n, "memberfunctionHandler:sym:name")); Replaceall(opname, "operator ", ""); - - if (strstr(Char(mangled_name), "__get__")) { - String *set_name = Copy(mangled_name); - if (!GetFlag(n, "feature:immutable")) { - Replaceall(set_name, "__get__", "__set__"); - Printf(f_class_ctors, " \"%s\", (fun args -> " "if args = (C_list [ raw_ptr ]) then %s args else %s args) ;\n", opname, mangled_name, set_name); - Delete(set_name); - } else { - Printf(f_class_ctors, " \"%s\", (fun args -> " "if args = (C_list [ raw_ptr ]) then %s args else C_void) ;\n", opname, mangled_name); - } - } else if (strstr(Char(mangled_name), "__set__")) { - ; /* Nothing ... handled by the case above */ - } else { - Printf(f_class_ctors, " \"%s\", %s ;\n", opname, mangled_name); - } - + Printf(f_class_ctors, " \"%s\", %s ;\n", opname, mangled_name); Delete(opname); } @@ -515,16 +543,6 @@ public: // adds local variables Wrapper_add_local(f, "args", "CAMLparam1(args)"); Wrapper_add_local(f, "ret", "SWIG_CAMLlocal2(swig_result,rv)"); - Wrapper_add_local(f, "_v", "int _v = 0"); - if (isOverloaded) { - Wrapper_add_local(f, "i", "int i"); - Wrapper_add_local(f, "argc", "int argc = caml_list_length(args)"); - Wrapper_add_local(f, "argv", "CAML_VALUE *argv"); - - Printv(f->code, - "argv = (CAML_VALUE *)malloc( argc * sizeof( CAML_VALUE ) );\n" - "for( i = 0; i < argc; i++ ) {\n" " argv[i] = caml_list_nth(args,i);\n" "}\n", NIL); - } d = SwigType_typedef_qualified(d); emit_parameter_variables(l, f); @@ -534,7 +552,18 @@ public: numargs = emit_num_arguments(l); numreq = emit_num_required(l); - + if (!isOverloaded) { + if (numargs > 0) { + if (numreq > 0) { + Printf(f->code, "if (caml_list_length(args) < %d || caml_list_length(args) > %d) {\n", numreq, numargs); + } else { + Printf(f->code, "if (caml_list_length(args) > %d) {\n", numargs); + } + Printf(f->code, "caml_invalid_argument(\"Incorrect number of arguments passed to '%s'\");\n}\n", iname); + } else { + Printf(f->code, "if (caml_list_length(args) > 0) caml_invalid_argument(\"'%s' takes no arguments\");\n", iname); + } + } Printf(f->code, "swig_result = Val_unit;\n"); // Now write code to extract the parameters (this is super ugly) @@ -550,10 +579,9 @@ public: pt = SwigType_typedef_qualified(pt); // Produce names of source and target - Clear(source); Clear(target); Clear(arg); - Printf(source, "caml_list_nth(args,%d)", i); + String *source = NewStringf("caml_list_nth(args,%d)", i); Printf(target, "%s", ln); Printv(arg, Getattr(p, "name"), NIL); @@ -577,6 +605,7 @@ public: if (i >= numreq) { Printf(f->code, "}\n"); } + Delete(source); } /* Insert constraint checking code */ @@ -676,6 +705,14 @@ public: Printv(f->code, tm, "\n", NIL); } } + + /* See if there is any return cleanup code */ + if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) { + Replaceall(tm, "$source", Swig_cresult_name()); + Printf(f->code, "%s\n", tm); + Delete(tm); + } + // Free any memory allocated by the function being wrapped.. if ((tm = Swig_typemap_lookup("swig_result", n, Swig_cresult_name(), 0))) { @@ -685,8 +722,6 @@ public: // Wrap things up (in a manner of speaking) Printv(f->code, tab4, "swig_result = caml_list_append(swig_result,rv);\n", NIL); - if (isOverloaded) - Printv(f->code, "free(argv);\n", NIL); Printv(f->code, tab4, "CAMLreturn(swig_result);\n", NIL); Printv(f->code, "}\n", NIL); @@ -703,7 +738,6 @@ public: "free(argv);\n" "CAMLreturn(%s(args));\n", &maxargs); - Wrapper_add_local(df, "_v", "int _v = 0"); Wrapper_add_local(df, "argv", "CAML_VALUE *argv"); /* Undifferentiate name .. this is the dispatch function */ @@ -717,8 +751,19 @@ public: Printv(df->code, "argv = (CAML_VALUE *)malloc( argc * sizeof( CAML_VALUE ) );\n" "for( i = 0; i < argc; i++ ) {\n" " argv[i] = caml_list_nth(args,i);\n" "}\n", NIL); - Printv(df->code, dispatch, "\n", NIL); - Printf(df->code, "failwith(\"No matching function for overloaded '%s'\");\n", iname); + Printv(df->code, dispatch, "\nfree(argv);\n", NIL); + Node *sibl = n; + while (Getattr(sibl, "sym:previousSibling")) + sibl = Getattr(sibl, "sym:previousSibling"); + String *protoTypes = NewString(""); + do { + String *fulldecl = Swig_name_decl(sibl); + Printf(protoTypes, "\n\" %s\\n\"", fulldecl); + Delete(fulldecl); + } while ((sibl = Getattr(sibl, "sym:nextSibling"))); + Printf(df->code, "caml_failwith(\"Wrong number or type of arguments for overloaded function '%s'.\\n\"" + "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", iname, protoTypes); + Delete(protoTypes); Printv(df->code, "}\n", NIL); Wrapper_print(df, f_wrappers); @@ -727,19 +772,20 @@ public: } } - Printf(f_mlbody, - "external %s_f : c_obj list -> c_obj list = \"%s\" ;;\n" - "let %s arg = match %s_f (fnhelper arg) with\n" - " [] -> C_void\n" - "| [x] -> (if %s then Gc.finalise \n" - " (fun x -> ignore ((invoke x) \"~\" C_void)) x) ; x\n" - "| lst -> C_list lst ;;\n", mangled_name, wname, mangled_name, mangled_name, newobj ? "true" : "false"); + if (expose_func) { + Printf(f_mlbody, "external %s_f : c_obj list -> c_obj list = \"%s\" ;;\n", mangled_name, wname); + Printf(f_mlbody, "let %s arg = match %s_f (%s(fnhelper arg)) with\n", mangled_name, mangled_name, + in_constructor && Swig_directorclass(getCurrentClass()) ? "director_core_helper " : ""); + Printf(f_mlbody, " [] -> C_void\n" + "| [x] -> (if %s then Gc.finalise \n" + " (fun x -> ignore ((invoke x) \"~\" C_void)) x) ; x\n" + "| lst -> C_list lst ;;\n", newobj ? "true" : "false"); + } - if (!classmode || in_constructor || in_destructor || static_member_function) + if ((!classmode || in_constructor || in_destructor || static_member_function) && expose_func) Printf(f_mlibody, "val %s : c_obj -> c_obj\n", mangled_name); Delete(proc_name); - Delete(source); Delete(target); Delete(arg); Delete(outarg); @@ -753,10 +799,11 @@ public: * variableWrapper() * * Create a link to a C variable. - * This creates a single function _wrap_swig_var_varname(). + * This creates a single function _wrap_varname(). * This function takes a single optional argument. If supplied, it means * we are setting this variable to some value. If omitted, it means we are - * simply evaluating this variable. In the set case we return C_void. + * simply evaluating this variable. We return the value of the variable + * in both cases. * * symname is the name of the variable with respect to C. This * may need to differ from the original name in the case of enums. @@ -772,9 +819,6 @@ public: String *proc_name = NewString(""); String *tm; - String *tm2 = NewString(""); - String *argnum = NewString("0"); - String *arg = NewString("SWIG_Field(args,0)"); Wrapper *f; if (!name) { @@ -794,14 +838,16 @@ public: // evaluation function names String *var_name = Swig_name_wrapper(iname); - // Build the name for scheme. + // Build the name for OCaml. Printv(proc_name, iname, NIL); Setattr(n, "wrap:name", proc_name); Printf(f->def, "SWIGEXT CAML_VALUE %s(CAML_VALUE args) {\n", var_name); // Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL); - Wrapper_add_local(f, "swig_result", "CAML_VALUE swig_result"); + Wrapper_add_local(f, "args", "CAMLparam1(args)"); + Wrapper_add_local(f, "swig_result", "SWIG_CAMLlocal1(swig_result)"); + Printf(f->code, "swig_result = Val_unit;\n"); if (!GetFlag(n, "feature:immutable")) { /* Check for a setting of the variable value */ @@ -810,13 +856,12 @@ public: Replaceall(tm, "$source", "args"); Replaceall(tm, "$target", name); Replaceall(tm, "$input", "args"); - /* Printv(f->code, tm, "\n",NIL); */ emit_action_code(n, f->code, tm); } else if ((tm = Swig_typemap_lookup("in", n, name, 0))) { Replaceall(tm, "$source", "args"); Replaceall(tm, "$target", name); Replaceall(tm, "$input", "args"); - Printv(f->code, tm, "\n", NIL); + emit_action_code(n, f->code, tm); } else { throw_unhandled_ocaml_type_error(t, "varin/in"); } @@ -834,12 +879,12 @@ public: Replaceall(tm, "$source", name); Replaceall(tm, "$target", "swig_result"); Replaceall(tm, "$result", "swig_result"); - Printf(f->code, "%s\n", tm); + emit_action_code(n, f->code, tm); } else { throw_unhandled_ocaml_type_error(t, "varout/out"); } - Printf(f->code, "\nreturn swig_result;\n"); + Printf(f->code, "\nCAMLreturn(swig_result);\n"); Printf(f->code, "}\n"); Wrapper_print(f, f_wrappers); @@ -860,9 +905,6 @@ public: Delete(var_name); Delete(proc_name); - Delete(argnum); - Delete(arg); - Delete(tm2); DelWrapper(f); return SWIG_OK; } @@ -890,10 +932,9 @@ public: virtual int constantWrapper(Node *n) { String *name = Getattr(n, "feature:symname"); SwigType *type = Getattr(n, "type"); - String *value = Getattr(n, "value"); + String *rawval = Getattr(n, "rawval"); + String *value = rawval ? rawval : Getattr(n, "value"); SwigType *qname = Getattr(n, "qualified:name"); - String *rvalue = NewString(""); - String *temp = 0; if (qname) value = qname; @@ -905,31 +946,8 @@ public: } // See if there's a typemap - Printv(rvalue, value, NIL); - if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 1)) { - temp = Copy(rvalue); - Clear(rvalue); - Printv(rvalue, "\"", temp, "\"", NIL); - Delete(temp); - } - if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 0)) { - temp = Copy(rvalue); - Clear(rvalue); - Printv(rvalue, "'", temp, "'", NIL); - Delete(temp); - } // Create variable and assign it a value - - Printf(f_header, "static %s = ", SwigType_lstr(type, name)); - bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0); - if ((SwigType_type(type) == T_STRING)) { - Printf(f_header, "\"%s\";\n", value); - } else if (SwigType_type(type) == T_CHAR && !is_enum_item) { - Printf(f_header, "\'%s\';\n", value); - } else { - Printf(f_header, "%s;\n", value); - } - + Printf(f_header, "static %s = %s;\n", SwigType_str(type, name), value); SetFlag(n, "feature:immutable"); variableWrapper(n); return SWIG_OK; @@ -1096,11 +1114,12 @@ public: int classHandler(Node *n) { String *name = Getattr(n, "name"); + classname = Getattr(n, "sym:name"); if (!name) return SWIG_OK; - String *mangled_sym_name = mangleNameForCaml(name); + String *mangled_name = mangleNameForCaml(name); String *this_class_def = NewString(f_classtemplate); String *name_normalized = normalizeTemplatedClassName(name); String *old_class_ctors = f_class_ctors; @@ -1109,7 +1128,6 @@ public: bool sizeof_feature = generate_sizeof && isSimpleType(name); - classname = mangled_sym_name; classmode = true; int rv = Language::classHandler(n); classmode = false; @@ -1117,15 +1135,15 @@ public: if (sizeof_feature) { Printf(f_wrappers, "SWIGEXT CAML_VALUE _wrap_%s_sizeof( CAML_VALUE args ) {\n" - " CAMLparam1(args);\n" " CAMLreturn(Val_int(sizeof(%s)));\n" "}\n", mangled_sym_name, name_normalized); + " CAMLparam1(args);\n" " CAMLreturn(Val_int(sizeof(%s)));\n" "}\n", mangled_name, name_normalized); - Printf(f_mlbody, "external __%s_sizeof : unit -> int = " "\"_wrap_%s_sizeof\"\n", classname, mangled_sym_name); + Printf(f_mlbody, "external __%s_sizeof : unit -> int = " "\"_wrap_%s_sizeof\"\n", mangled_name, mangled_name); } /* Insert sizeof operator for concrete classes */ if (sizeof_feature) { - Printv(f_class_ctors, "\"sizeof\" , (fun args -> C_int (__", classname, "_sizeof ())) ;\n", NIL); + Printv(f_class_ctors, "\"sizeof\" , (fun args -> C_int (__", mangled_name, "_sizeof ())) ;\n", NIL); } /* Handle up-casts in a nice way */ List *baselist = Getattr(n, "bases"); @@ -1144,7 +1162,7 @@ public: } } - Replaceall(this_class_def, "$classname", classname); + Replaceall(this_class_def, "$classname", mangled_name); Replaceall(this_class_def, "$normalized", name_normalized); Replaceall(this_class_def, "$realname", name); Replaceall(this_class_def, "$baselist", base_classes); @@ -1157,7 +1175,7 @@ public: Multiwrite(this_class_def); - Setattr(n, "ocaml:ctor", classname); + Setattr(n, "ocaml:ctor", mangled_name); return rv; } @@ -1396,8 +1414,7 @@ public: pure_virtual = true; } } - - Wrapper_add_local(w, "swig_result", "CAMLparam0();\n" "SWIG_CAMLlocal2(swig_result,args)"); + Printf(w->locals, "CAMLparam0();\n"); /* determine if the method returns a pointer */ is_pointer = SwigType_ispointer_return(decl); @@ -1408,44 +1425,88 @@ public: String *pclassname = NewStringf("SwigDirector_%s", classname); String *qualified_name = NewStringf("%s::%s", pclassname, name); SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); - target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); - Printf(w->def, "%s {", target); + target = Swig_method_decl(rtype, decl, qualified_name, l, 0); + Printf(w->def, "%s", target); Delete(qualified_name); Delete(target); /* header declaration */ - target = Swig_method_decl(rtype, decl, name, l, 0, 1); - Printf(declaration, " virtual %s;", target); + target = Swig_method_decl(rtype, decl, name, l, 1); + Printf(declaration, " virtual %s", target); Delete(target); + // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } + ParmList *throw_parm_list = 0; + if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { + Parm *p; + int gencomma = 0; + + Append(w->def, " throw("); + Append(declaration, " throw("); + + if (throw_parm_list) + Swig_typemap_attach_parms("throws", throw_parm_list, 0); + for (p = throw_parm_list; p; p = nextSibling(p)) { + if (Getattr(p, "tmap:throws")) { + if (gencomma++) { + Append(w->def, ", "); + Append(declaration, ", "); + } + String *str = SwigType_str(Getattr(p, "type"), 0); + Append(w->def, str); + Append(declaration, str); + Delete(str); + } + } + Append(w->def, ")"); + Append(declaration, ")"); + } + Append(w->def, " {"); + Append(declaration, ";\n"); /* declare method return value * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { - Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL); + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { + String *cres = SwigType_lstr(returntype, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); } } if (ignored_method) { if (!pure_virtual) { - if (!is_void) - Printf(w->code, "return "); String *super_call = Swig_method_call(super, l); - Printf(w->code, "%s;\n", super_call); + if (is_void) + Printf(w->code, "%s;\n", super_call); + else + Printf(w->code, "CAMLreturn_type(%s);\n", super_call); Delete(super_call); } else { Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); } } else { + Wrapper_add_local(w, "swig_result", "SWIG_CAMLlocal2(swig_result, args)"); /* attach typemaps to arguments (C/C++ -> Ocaml) */ String *arglist = NewString(""); Swig_director_parms_fixup(l); Swig_typemap_attach_parms("in", l, 0); - Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorin", l, w); Swig_typemap_attach_parms("directorargout", l, w); Parm *p; @@ -1555,10 +1616,12 @@ public: /* wrap complex arguments to values */ Printv(w->code, wrap_args, NIL); - /* pass the method call on to the Python object */ + /* pass the method call on to the OCaml object */ Printv(w->code, "swig_result = caml_swig_alloc(1,C_list);\n" "SWIG_Store_field(swig_result,0,args);\n" "args = swig_result;\n" "swig_result = Val_unit;\n", 0); - Printf(w->code, "swig_result = " "callback3(*caml_named_value(\"swig_runmethod\")," "swig_get_self(),copy_string(\"%s\"),args);\n", Getattr(n, "name")); + Printf(w->code, "static CAML_VALUE *swig_ocaml_func_val = NULL;\n" "if (!swig_ocaml_func_val) {\n"); + Printf(w->code, " swig_ocaml_func_val = caml_named_value(\"swig_runmethod\");\n }\n"); + Printf(w->code, "swig_result = caml_callback3(*swig_ocaml_func_val,swig_get_self(),caml_copy_string(\"%s\"),args);\n", Getattr(n, "name")); /* exception handling */ tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0); if (!tm) { @@ -1574,7 +1637,7 @@ public: /* * Python method may return a simple object, or a tuple. - * for in/out aruments, we have to extract the appropriate values from the + * for in/out arguments, we have to extract the appropriate values from the * argument list, then marshal everything back to C/C++ (return value and * output arguments). */ @@ -1633,6 +1696,8 @@ public: Printf(w->code, "CAMLreturn_type(*c_result);\n"); } } + } else { + Printf(w->code, "CAMLreturn0;\n"); } Printf(w->code, "}\n"); @@ -1698,7 +1763,7 @@ public: Wrapper *w = NewWrapper(); String *call; String *basetype = Getattr(parent, "classtype"); - String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); + String *target = Swig_method_decl(0, decl, classname, parms, 0); call = Swig_csuperclass_call(0, basetype, superparms); Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call); Delete(target); @@ -1709,7 +1774,7 @@ public: /* constructor header */ { - String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); + String *target = Swig_method_decl(0, decl, classname, parms, 1); Printf(f_directors_h, " %s;\n", target); Delete(target); } @@ -1799,9 +1864,9 @@ public: } String *runtimeCode() { - String *s = Swig_include_sys("ocaml.swg"); + String *s = Swig_include_sys("ocamlrun.swg"); if (!s) { - Printf(stderr, "*** Unable to open 'ocaml.swg'\n"); + Printf(stderr, "*** Unable to open 'ocamlrun.swg'\n"); s = NewString(""); } return s; diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index b977609a8..1297d2445 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -19,10 +19,8 @@ static String *op_prefix = 0; static const char *usage = "\ Octave Options (available with -octave)\n\ - -cppcast - Enable C++ casting operators (default)\n\ -globals - Set used to access C global variables [default: 'cvar']\n\ Use '.' to load C global variables into module namespace\n\ - -nocppcast - Disable C++ casting operators\n\ -opprefix - Prefix for global operator functions [default: 'op_']\n\ \n"; @@ -92,8 +90,7 @@ public: } virtual void main(int argc, char *argv[]) { - int cppcast = 1; - + for (int i = 1; i < argc; i++) { if (argv[i]) { if (strcmp(argv[i], "-help") == 0) { @@ -116,12 +113,13 @@ public: } else { Swig_arg_error(); } - } else if (strcmp(argv[i], "-cppcast") == 0) { - cppcast = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nocppcast") == 0) { - cppcast = 0; - Swig_mark_arg(i); + } else if (strcmp(argv[i], "-cppcast") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]); + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-nocppcast") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]); + Swig_mark_arg(i); + SWIG_exit(EXIT_FAILURE); } } } @@ -130,8 +128,6 @@ public: global_name = NewString("cvar"); if (!op_prefix) op_prefix = NewString("op_"); - if(cppcast) - Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0); SWIG_library_directory("octave"); Preprocessor_define("SWIGOCTAVE 1", 0); @@ -139,7 +135,7 @@ public: SWIG_typemap_lang("octave"); allow_overloading(); - // Octave API is C++, so output must be C++ compatibile even when wrapping C code + // Octave API is C++, so output must be C++ compatible even when wrapping C code if (!cparse_cplusplus) Swig_cparse_cplusplusout(1); } @@ -422,13 +418,14 @@ public: * The "lname" attribute in each parameter in plist will be contain a parameter name * ----------------------------------------------------------------------------- */ - void addMissingParameterNames(ParmList *plist, int arg_offset) { + void addMissingParameterNames(Node* n, ParmList *plist, int arg_offset) { Parm *p = plist; int i = arg_offset; while (p) { if (!Getattr(p, "lname")) { - String *pname = Swig_cparm_name(p, i); - Delete(pname); + String *name = makeParameterName(n, p, i); + Setattr(p, "lname", name); + Delete(name); } i++; p = nextSibling(p); @@ -440,14 +437,14 @@ public: ParmList *plist = CopyParmList(Getattr(n, "parms")); Parm *p; Parm *pnext; - int start_arg_num = is_wrapping_class() ? 1 : 0; + int arg_num = is_wrapping_class() ? 1 : 0; - addMissingParameterNames(plist, start_arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms + addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms Swig_typemap_attach_parms("in", plist, 0); Swig_typemap_attach_parms("doc", plist, 0); - for (p = plist; p; p = pnext) { + for (p = plist; p; p = pnext, arg_num++) { String *tm = Getattr(p, "tmap:in"); if (tm) { @@ -469,9 +466,10 @@ public: value = Getattr(p, "tmap:doc:value"); } - name = name ? name : Getattr(p, "name"); - name = name ? name : Getattr(p, "lname"); - name = Swig_name_make(p, 0, name, 0, 0); // rename parameter if a keyword + String *made_name = 0; + if (!name) { + name = made_name = makeParameterName(n, p, arg_num); + } type = type ? type : Getattr(p, "type"); value = value ? value : Getattr(p, "value"); @@ -507,7 +505,7 @@ public: Delete(type_str); Delete(tex_name); - Delete(name); + Delete(made_name); } if (pdocs) Setattr(n, "feature:pdocs", pdocs); @@ -1234,7 +1232,7 @@ public: Wrapper *w = NewWrapper(); String *call; String *basetype = Getattr(parent, "classtype"); - String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); + String *target = Swig_method_decl(0, decl, classname, parms, 0); call = Swig_csuperclass_call(0, basetype, superparms); Printf(w->def, "%s::%s: %s," "\nSwig::Director(static_cast<%s*>(this)) { \n", classname, target, call, basetype); Append(w->def, "}\n"); @@ -1246,7 +1244,7 @@ public: // constructor header { - String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); + String *target = Swig_method_decl(0, decl, classname, parms, 1); Printf(f_directors_h, " %s;\n", target); Delete(target); } @@ -1310,17 +1308,21 @@ public: String *pclassname = NewStringf("SwigDirector_%s", classname); String *qualified_name = NewStringf("%s::%s", pclassname, name); SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); - target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); + target = Swig_method_decl(rtype, decl, qualified_name, l, 0); Printf(w->def, "%s", target); Delete(qualified_name); Delete(target); // header declaration - target = Swig_method_decl(rtype, decl, name, l, 0, 1); + target = Swig_method_decl(rtype, decl, name, l, 1); Printf(declaration, " virtual %s", target); Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { @@ -1355,11 +1357,19 @@ public: // declare method return value // if the return value is a reference or const reference, a specialized typemap must // handle it, including declaration of c_result ($result). - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { - String *cres = SwigType_lstr(returntype, "c_result"); - Printf(w->code, "%s;\n", cres); - Delete(cres); + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { + String *cres = SwigType_lstr(returntype, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); } } @@ -1381,7 +1391,7 @@ public: Swig_director_parms_fixup(l); Swig_typemap_attach_parms("in", l, 0); - Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorin", l, w); Swig_typemap_attach_parms("directorargout", l, w); Parm *p; diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx index 330294efd..5d278107c 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -185,7 +185,8 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { nodes[j] = t; break; } else if ((differ == 0) && (Strcmp(t1, "0") == 0)) { - t1 = Getattr(p1, "ltype"); + t1 = Getattr(p1, "equivtype"); + t1 = t1 ? t1 : Getattr(p1, "ltype"); if (!t1) { t1 = SwigType_ltype(Getattr(p1, "type")); if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) { @@ -193,7 +194,8 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { } Setattr(p1, "ltype", t1); } - t2 = Getattr(p2, "ltype"); + t2 = Getattr(p2, "equivtype"); + t2 = t2 ? t2 : Getattr(p2, "ltype"); if (!t2) { t2 = SwigType_ltype(Getattr(p2, "type")); if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) { @@ -231,9 +233,21 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { } if (!differ) { /* See if declarations differ by const only */ - String *d1 = Getattr(nodes[i].n, "decl"); - String *d2 = Getattr(nodes[j].n, "decl"); - if (d1 && d2) { + String *decl1 = Getattr(nodes[i].n, "decl"); + String *decl2 = Getattr(nodes[j].n, "decl"); + if (decl1 && decl2) { + /* Remove ref-qualifiers. Note that rvalue ref-qualifiers are already ignored and + * it is illegal to overload a function with and without ref-qualifiers. So with + * all the combinations of ref-qualifiers and cv-qualifiers, we just detect + * the cv-qualifier (const) overloading. */ + String *d1 = Copy(decl1); + String *d2 = Copy(decl2); + if (SwigType_isreference(d1) || SwigType_isrvalue_reference(d1)) { + Delete(SwigType_pop(d1)); + } + if (SwigType_isreference(d2) || SwigType_isrvalue_reference(d2)) { + Delete(SwigType_pop(d2)); + } String *dq1 = Copy(d1); String *dq2 = Copy(d2); if (SwigType_isconst(d1)) { @@ -428,7 +442,7 @@ String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int * /* Loop over the functions */ - bool emitcheck = 1; + bool emitcheck = true; for (i = 0; i < nfunc; i++) { int fn = 0; Node *ni = Getitem(dispatch, i); @@ -504,7 +518,7 @@ String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int * if (tml) Replaceid(tml, Getattr(pl, "lname"), "_v"); if (!tml || Cmp(tm, tml)) - emitcheck = 1; + emitcheck = true; //printf("tmap: %s[%d] (%d) => %s\n\n", // Char(Getattr(nk, "sym:name")), // l, emitcheck, tml?Char(tml):0); @@ -596,7 +610,7 @@ String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int * /* Fast dispatch mechanism, provided by Salvador Fandi~no Garc'ia (#930586). */ -String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *maxargs) { +static String *overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *maxargs, const_String_or_char_ptr fmt_fastdispatch) { int i, j; *maxargs = 1; @@ -639,6 +653,7 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int * // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll)); + bool emitcheck = false; int num_braces = 0; bool test = (Len(coll) > 0 && num_arguments); if (test) { @@ -659,7 +674,7 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int * /* if all the wrappers have the same type check on this argument we can optimize it out */ - bool emitcheck = 0; + emitcheck = false; for (int k = 0; k < Len(coll) && !emitcheck; k++) { Node *nk = Getitem(coll, k); Parm *pk = Getattr(nk, "wrap:parms"); @@ -681,7 +696,7 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int * if (tml) Replaceid(tml, Getattr(pl, "lname"), "_v"); if (!tml || Cmp(tm, tml)) - emitcheck = 1; + emitcheck = true; //printf("tmap: %s[%d] (%d) => %s\n\n", // Char(Getattr(nk, "sym:name")), // l, emitcheck, tml?Char(tml):0); @@ -738,8 +753,8 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int * for ( /* empty */ ; num_braces > 0; num_braces--) Printf(f, "}\n"); - - String *lfmt = ReplaceFormat(fmt, num_arguments); + // The language module may want to generate different code for last overloaded function called (with same number of arguments) + String *lfmt = ReplaceFormat(!emitcheck && fmt_fastdispatch ? fmt_fastdispatch : fmt, num_arguments); Printf(f, Char(lfmt), Getattr(ni, "wrap:name")); Printf(f, "}\n"); /* braces closes "if" for this method */ @@ -756,10 +771,10 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int * return f; } -String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxargs) { +String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxargs, const_String_or_char_ptr fmt_fastdispatch) { if (fast_dispatch_mode || GetFlag(n, "feature:fastdispatch")) { - return Swig_overload_dispatch_fast(n, fmt, maxargs); + return overload_dispatch_fast(n, fmt, maxargs, fmt_fastdispatch); } int i, j; diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index 406568b16..dfa85f3c8 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -16,11 +16,9 @@ #include static const char *usage = "\ -Perl5 Options (available with -perl5)\n\ +Perl 5 Options (available with -perl5)\n\ -compat - Compatibility mode\n\ -const - Wrap constants as constants and not variables (implies -proxy)\n\ - -cppcast - Enable C++ casting operators\n\ - -nocppcast - Disable C++ casting operators, useful for generating bugs\n\ -nopm - Do not generate the .pm file\n\ -noproxy - Don't create proxy classes\n\ -proxy - Create proxy classes\n\ @@ -148,7 +146,6 @@ public: virtual void main(int argc, char *argv[]) { int i = 1; - int cppcast = 1; SWIG_library_directory("perl5"); @@ -189,25 +186,22 @@ public: } else if (strcmp(argv[i],"-v") == 0) { Swig_mark_arg(i); verbose++; - } else if (strcmp(argv[i], "-cppcast") == 0) { - cppcast = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nocppcast") == 0) { - cppcast = 0; - Swig_mark_arg(i); } else if (strcmp(argv[i], "-compat") == 0) { compat = 1; Swig_mark_arg(i); } else if (strcmp(argv[i], "-help") == 0) { fputs(usage, stdout); + } else if (strcmp(argv[i], "-cppcast") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]); + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-nocppcast") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]); + Swig_mark_arg(i); + SWIG_exit(EXIT_FAILURE); } } } - if (cppcast) { - Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0); - } - Preprocessor_define("SWIGPERL 1", 0); // SWIGPERL5 is deprecated, and no longer documented. Preprocessor_define("SWIGPERL5 1", 0); @@ -900,6 +894,15 @@ public: Printf(f->code, "%s\n", tm); } + if (director_method) { + if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) { + Replaceall(tm, "$input", Swig_cresult_name()); + Replaceall(tm, "$result", "ST(argvi)"); + Printf(f->code, "%s\n", tm); + Delete(tm); + } + } + Printv(f->code, "XSRETURN(argvi);\n", "fail:\n", cleanup, "SWIG_croak_null();\n" "}\n" "}\n", NIL); /* Add the dXSARGS last */ @@ -2018,7 +2021,7 @@ public: Wrapper *w = NewWrapper(); String *call; String *basetype = Getattr(parent, "classtype"); - String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); + String *target = Swig_method_decl(0, decl, classname, parms, 0); call = Swig_csuperclass_call(0, basetype, superparms); Printf(w->def, "%s::%s: %s, Swig::Director(self) { \n", classname, target, call); Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype); @@ -2031,7 +2034,7 @@ public: /* constructor header */ { - String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); + String *target = Swig_method_decl(0, decl, classname, parms, 1); Printf(f_directors_h, " %s;\n", target); Delete(target); } @@ -2080,16 +2083,20 @@ public: String *pclassname = NewStringf("SwigDirector_%s", classname); String *qualified_name = NewStringf("%s::%s", pclassname, name); SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); - target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); + target = Swig_method_decl(rtype, decl, qualified_name, l, 0); Printf(w->def, "%s", target); Delete(qualified_name); Delete(target); /* header declaration */ - target = Swig_method_decl(rtype, decl, name, l, 0, 1); + target = Swig_method_decl(rtype, decl, name, l, 1); Printf(declaration, " virtual %s", target); Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { @@ -2125,17 +2132,26 @@ public: * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { String *cres = SwigType_lstr(returntype, "c_result"); Printf(w->code, "%s;\n", cres); Delete(cres); } - if (!ignored_method) { - String *pres = NewStringf("SV *%s", Swig_cresult_name()); - Wrapper_add_local(w, Swig_cresult_name(), pres); - Delete(pres); - } + } + + if (!is_void && !ignored_method) { + String *pres = NewStringf("SV *%s", Swig_cresult_name()); + Wrapper_add_local(w, Swig_cresult_name(), pres); + Delete(pres); } if (ignored_method) { @@ -2158,7 +2174,7 @@ public: /* remove the wrapper 'w' since it was producing spurious temps */ Swig_typemap_attach_parms("in", l, 0); - Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorin", l, w); Swig_typemap_attach_parms("directorargout", l, w); Wrapper_add_local(w, "SP", "dSP"); @@ -2332,7 +2348,7 @@ public: /* * Python method may return a simple object, or a tuple. - * for in/out aruments, we have to extract the appropriate PyObjects from the tuple, + * for in/out arguments, we have to extract the appropriate PyObjects from the tuple, * then marshal everything back to C/C++ (return value and output arguments). * */ @@ -2486,9 +2502,12 @@ public: Delete(mangle); Delete(ptype); - if (Getattr(n, "throw")) { - Printf(f_directors_h, " virtual ~%s() throw ();\n", DirectorClassName); - Printf(f_directors, "%s::~%s() throw () {%s}\n\n", DirectorClassName, DirectorClassName, body); + if (Getattr(n, "noexcept")) { + Printf(f_directors_h, " virtual ~%s() noexcept;\n", DirectorClassName); + Printf(f_directors, "%s::~%s() noexcept {%s}\n\n", DirectorClassName, DirectorClassName, body); + } else if (Getattr(n, "throw")) { + Printf(f_directors_h, " virtual ~%s() throw();\n", DirectorClassName); + Printf(f_directors, "%s::~%s() throw() {%s}\n\n", DirectorClassName, DirectorClassName, body); } else { Printf(f_directors_h, " virtual ~%s();\n", DirectorClassName); Printf(f_directors, "%s::~%s() {%s}\n\n", DirectorClassName, DirectorClassName, body); diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 02bd827f8..b192d6f6e 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -12,7 +12,7 @@ * ----------------------------------------------------------------------------- */ -/* FIXME: PHP5 OO wrapping TODO list: +/* FIXME: PHP OO wrapping TODO list: * * Medium term: * @@ -43,7 +43,7 @@ #include static const char *usage = "\ -PHP Options (available with -php)\n\ +PHP 7 Options (available with -php7)\n\ -noproxy - Don't generate proxy classes.\n\ -prefix - Prepend to all class names in PHP wrappers\n\ \n"; @@ -96,10 +96,16 @@ static String *all_cs_entry; static String *pragma_incl; static String *pragma_code; static String *pragma_phpinfo; +static String *pragma_version; static String *s_oowrappers; static String *s_fakeoowrappers; static String *s_phpclasses; +/* To reduce code size (generated and compiled) we only want to emit each + * different arginfo once, so we need to track which have been used. + */ +static Hash *arginfo_used; + /* Variables for using PHP classes */ static Node *current_class = 0; @@ -129,20 +135,19 @@ extern "C" { static void SwigPHP_emit_resource_registrations() { Iterator ki; + bool emitted_default_dtor = false; if (!zend_types) return; ki = First(zend_types); if (ki.key) - Printf(s_oinit, "\n/* Register resource destructors for pointer types */\n"); + Printf(s_oinit, "\n /* Register resource destructors for pointer types */\n"); while (ki.key) { DOH *key = ki.key; Node *class_node = ki.item; String *human_name = key; - - // Write out destructor function header - Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(_wrap_destroy%s) {\n", key); + String *rsrc_dtor_name = NULL; // write out body if (class_node != NOTCLASS) { @@ -152,51 +157,42 @@ static void SwigPHP_emit_resource_registrations() { human_name = Getattr(class_node, "name"); // Do we have a known destructor for this type? if (destructor) { - Printf(s_wrappers, " %s(rsrc, SWIGTYPE%s->name TSRMLS_CC);\n", destructor, key); - } else { - Printf(s_wrappers, " /* No destructor for class %s */\n", human_name); - Printf(s_wrappers, " efree(rsrc->ptr);\n"); + rsrc_dtor_name = NewStringf("_wrap_destroy%s", key); + // Write out custom destructor function + Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(%s) {\n", rsrc_dtor_name); + Printf(s_wrappers, " %s(res, SWIGTYPE%s->name);\n", destructor, key); + Printf(s_wrappers, "}\n"); } - } else { - Printf(s_wrappers, " /* No destructor for simple type %s */\n", key); - Printf(s_wrappers, " efree(rsrc->ptr);\n"); } - // close function - Printf(s_wrappers, "}\n"); + if (!rsrc_dtor_name) { + rsrc_dtor_name = NewString("_swig_default_rsrc_destroy"); + if (!emitted_default_dtor) { + // Write out custom destructor function + Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(%s) {\n", rsrc_dtor_name); + Printf(s_wrappers, " efree(res->ptr);\n"); + Printf(s_wrappers, "}\n"); + emitted_default_dtor = true; + } + } // declare le_swig_ to store php registration Printf(s_vdecl, "static int le_swig_%s=0; /* handle for %s */\n", key, human_name); // register with php - Printf(s_oinit, "le_swig_%s=zend_register_list_destructors_ex" - "(_wrap_destroy%s,NULL,(char *)(SWIGTYPE%s->name),module_number);\n", key, key, key); + Printf(s_oinit, " le_swig_%s=zend_register_list_destructors_ex" + "(%s, NULL, SWIGTYPE%s->name, module_number);\n", key, rsrc_dtor_name, key); // store php type in class struct - Printf(s_oinit, "SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key); + Printf(s_oinit, " SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key); + + Delete(rsrc_dtor_name); ki = Next(ki); } } class PHP : public Language { - String *emit_action(Node *n) { - // Adjust wrap:action to add TSRMLS_CC. - String * action = Getattr(n, "wrap:action"); - if (action) { - char * p = Strstr(action, "Swig::DirectorPureVirtualException::raise(\""); - if (p) { - p += strlen("Swig::DirectorPureVirtualException::raise(\""); - p = strchr(p, '"'); - if (p) { - ++p; - Insert(action, (int)(p - Char(action)), " TSRMLS_CC"); - } - } - } - return ::emit_action(n); - } - public: PHP() { director_language = 1; @@ -208,7 +204,6 @@ public: virtual void main(int argc, char *argv[]) { SWIG_library_directory("php"); - SWIG_config_cppext("cpp"); for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-prefix") == 0) { @@ -225,25 +220,11 @@ public: Swig_mark_arg(i); } else if (strcmp(argv[i], "-help") == 0) { fputs(usage, stdout); - } else if (strcmp(argv[i], "-make") == 0 || - strcmp(argv[i], "-withc") == 0 || - strcmp(argv[i], "-withcxx") == 0) { - Printf(stderr, "*** %s is no longer supported.\n", argv[i]); - SWIG_exit(EXIT_FAILURE); - } else if (strcmp(argv[i], "-phpfull") == 0 || - strcmp(argv[i], "-withlibs") == 0 || - strcmp(argv[i], "-withincs") == 0) { - Printf(stderr, "*** %s is no longer supported.\n*** We recommend building as a dynamically loadable module.\n", argv[i]); - SWIG_exit(EXIT_FAILURE); - } else if (strcmp(argv[i], "-dlname") == 0) { - Printf(stderr, "*** -dlname is no longer supported.\n*** If you want to change the module name, use -module instead.\n"); - SWIG_exit(EXIT_FAILURE); } } Preprocessor_define("SWIGPHP 1", 0); - // SWIGPHP5 is deprecated, and no longer documented. - Preprocessor_define("SWIGPHP5 1", 0); + Preprocessor_define("SWIGPHP7 1", 0); SWIG_typemap_lang("php"); SWIG_config_file("php.swg"); allow_overloading(); @@ -267,7 +248,7 @@ public: } /* Set comparison with null for ConstructorToFunction */ - setSubclassInstanceCheck(NewString("$arg->type != IS_NULL")); + setSubclassInstanceCheck(NewString("Z_TYPE_P($arg) != IS_NULL")); /* Initialize all of the output files */ String *outfile = Getattr(n, "outfile"); @@ -282,17 +263,17 @@ public: f_runtime = NewStringEmpty(); /* sections of the output file */ - s_init = NewString("/* init section */\n"); - r_init = NewString("/* rinit section */\n"); - s_shutdown = NewString("/* shutdown section */\n"); - r_shutdown = NewString("/* rshutdown section */\n"); + s_init = NewStringEmpty(); + r_init = NewStringEmpty(); + s_shutdown = NewStringEmpty(); + r_shutdown = NewStringEmpty(); s_header = NewString("/* header section */\n"); s_wrappers = NewString("/* wrapper section */\n"); /* subsections of the init section */ - s_vinit = NewString("/* vinit subsection */\n"); + s_vinit = NewStringEmpty(); s_vdecl = NewString("/* vdecl subsection */\n"); - s_cinit = NewString("/* cinit subsection */\n"); - s_oinit = NewString("/* oinit subsection */\n"); + s_cinit = NewString(" /* cinit subsection */\n"); + s_oinit = NewString(" /* oinit subsection */\n"); pragma_phpinfo = NewStringEmpty(); s_phpclasses = NewString("/* PHP Proxy Classes */\n"); f_directors_h = NewStringEmpty(); @@ -379,10 +360,11 @@ public: /* sub-sections of the php file */ pragma_code = NewStringEmpty(); pragma_incl = NewStringEmpty(); + pragma_version = NULL; /* Initialize the rest of the module */ - Printf(s_oinit, "ZEND_INIT_MODULE_GLOBALS(%s, %s_init_globals, %s_destroy_globals);\n", module, module, module); + Printf(s_oinit, " ZEND_INIT_MODULE_GLOBALS(%s, %s_init_globals, NULL);\n", module, module); /* start the header section */ Printf(s_header, "ZEND_BEGIN_MODULE_GLOBALS(%s)\n", module); @@ -390,21 +372,16 @@ public: Printf(s_header, "int error_code;\n"); Printf(s_header, "ZEND_END_MODULE_GLOBALS(%s)\n", module); Printf(s_header, "ZEND_DECLARE_MODULE_GLOBALS(%s)\n", module); - Printf(s_header, "#ifdef ZTS\n"); - Printf(s_header, "#define SWIG_ErrorMsg() TSRMG(%s_globals_id, zend_%s_globals *, error_msg )\n", module, module); - Printf(s_header, "#define SWIG_ErrorCode() TSRMG(%s_globals_id, zend_%s_globals *, error_code )\n", module, module); - Printf(s_header, "#else\n"); - Printf(s_header, "#define SWIG_ErrorMsg() (%s_globals.error_msg)\n", module); - Printf(s_header, "#define SWIG_ErrorCode() (%s_globals.error_code)\n", module); - Printf(s_header, "#endif\n\n"); + Printf(s_header, "#define SWIG_ErrorMsg() ZEND_MODULE_GLOBALS_ACCESSOR(%s, error_msg)\n", module); + Printf(s_header, "#define SWIG_ErrorCode() ZEND_MODULE_GLOBALS_ACCESSOR(%s, error_code)\n", module); /* The following can't go in Lib/php/phprun.swg as it uses SWIG_ErrorMsg(), etc * which has to be dynamically generated as it depends on the module name. */ Append(s_header, "#ifdef __GNUC__\n"); - Append(s_header, "static void SWIG_FAIL(TSRMLS_D) __attribute__ ((__noreturn__));\n"); + Append(s_header, "static void SWIG_FAIL(void) __attribute__ ((__noreturn__));\n"); Append(s_header, "#endif\n\n"); - Append(s_header, "static void SWIG_FAIL(TSRMLS_D) {\n"); + Append(s_header, "static void SWIG_FAIL(void) {\n"); Append(s_header, " zend_error(SWIG_ErrorCode(), \"%s\", SWIG_ErrorMsg());\n"); // zend_error() should never return with the parameters we pass, but if it // does, we really don't want to let SWIG_FAIL() return. This also avoids @@ -417,41 +394,36 @@ public: Printf(s_header, " globals->error_code = default_error_code;\n"); Printf(s_header, "}\n"); - Printf(s_header, "static void %s_destroy_globals(zend_%s_globals * globals) { (void)globals; }\n", module, module); - - Printf(s_header, "\n"); - Printf(s_header, "static void SWIG_ResetError(TSRMLS_D) {\n"); + Printf(s_header, "static void SWIG_ResetError(void) {\n"); Printf(s_header, " SWIG_ErrorMsg() = default_error_msg;\n"); Printf(s_header, " SWIG_ErrorCode() = default_error_code;\n"); Printf(s_header, "}\n"); Append(s_header, "\n"); Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_alter_newobject) {\n", module); - Append(s_header, " zval **args[2];\n"); + Append(s_header, " zval args[2];\n"); Append(s_header, " swig_object_wrapper *value;\n"); - Append(s_header, " int type;\n"); Append(s_header, "\n"); - Append(s_header, " SWIG_ResetError(TSRMLS_C);\n"); + Append(s_header, " SWIG_ResetError();\n"); Append(s_header, " if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {\n"); Append(s_header, " WRONG_PARAM_COUNT;\n"); Append(s_header, " }\n"); Append(s_header, "\n"); - Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n"); - Append(s_header, " value->newobject = zval_is_true(*args[1]);\n"); + Append(s_header, " value = (swig_object_wrapper *) Z_RES_VAL(args[0]);\n"); + Append(s_header, " value->newobject = zval_is_true(&args[1]);\n"); Append(s_header, "\n"); Append(s_header, " return;\n"); Append(s_header, "}\n"); Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_get_newobject) {\n", module); - Append(s_header, " zval **args[1];\n"); + Append(s_header, " zval args[1];\n"); Append(s_header, " swig_object_wrapper *value;\n"); - Append(s_header, " int type;\n"); Append(s_header, "\n"); - Append(s_header, " SWIG_ResetError(TSRMLS_C);\n"); + Append(s_header, " SWIG_ResetError();\n"); Append(s_header, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n"); Append(s_header, " WRONG_PARAM_COUNT;\n"); Append(s_header, " }\n"); Append(s_header, "\n"); - Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n"); + Append(s_header, " value = (swig_object_wrapper *) Z_RES_VAL(args[0]);\n"); Append(s_header, " RETVAL_LONG(value->newobject);\n"); Append(s_header, "\n"); Append(s_header, " return;\n"); @@ -496,17 +468,10 @@ public: Printf(f_h, "#else\n"); Printf(f_h, "# define PHP_%s_API\n", cap_module); Printf(f_h, "#endif\n\n"); - Printf(f_h, "#ifdef ZTS\n"); - Printf(f_h, "#include \"TSRM.h\"\n"); - Printf(f_h, "#endif\n\n"); - Printf(f_h, "PHP_MINIT_FUNCTION(%s);\n", module); - Printf(f_h, "PHP_MSHUTDOWN_FUNCTION(%s);\n", module); - Printf(f_h, "PHP_RINIT_FUNCTION(%s);\n", module); - Printf(f_h, "PHP_RSHUTDOWN_FUNCTION(%s);\n", module); - Printf(f_h, "PHP_MINFO_FUNCTION(%s);\n\n", module); /* start the arginfo section */ s_arginfo = NewString("/* arginfo subsection */\n"); + arginfo_used = NewHash(); /* start the function entry section */ s_entry = NewString("/* entry subsection */\n"); @@ -518,93 +483,146 @@ public: Printf(s_entry, "/* Every non-class user visible function must have an entry here */\n"); Printf(s_entry, "static zend_function_entry %s_functions[] = {\n", module); - /* start the init section */ - Append(s_init, "#if ZEND_MODULE_API_NO <= 20090626\n"); - Append(s_init, "#undef ZEND_MODULE_BUILD_ID\n"); - Append(s_init, "#define ZEND_MODULE_BUILD_ID (char*)\"API\" ZEND_TOSTR(ZEND_MODULE_API_NO) ZEND_BUILD_TS ZEND_BUILD_DEBUG ZEND_BUILD_SYSTEM ZEND_BUILD_EXTRA\n"); - Append(s_init, "#endif\n"); - Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n", NIL); - Printf(s_init, " STANDARD_MODULE_HEADER,\n"); - Printf(s_init, " (char*)\"%s\",\n", module); - Printf(s_init, " %s_functions,\n", module); - Printf(s_init, " PHP_MINIT(%s),\n", module); - Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module); - Printf(s_init, " PHP_RINIT(%s),\n", module); - Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module); - Printf(s_init, " PHP_MINFO(%s),\n", module); - Printf(s_init, " NO_VERSION_YET,\n"); - Printf(s_init, " STANDARD_MODULE_PROPERTIES\n"); - Printf(s_init, "};\n"); - Printf(s_init, "zend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", module); + /* Emit all of the code */ + Language::top(n); - Printf(s_init, "#ifdef __cplusplus\n"); - Printf(s_init, "extern \"C\" {\n"); - Printf(s_init, "#endif\n"); - // We want to write "SWIGEXPORT ZEND_GET_MODULE(%s)" but ZEND_GET_MODULE - // in PHP5 has "extern "C" { ... }" around it so we can't do that. - Printf(s_init, "SWIGEXPORT zend_module_entry *get_module(void) { return &%s_module_entry; }\n", module); - Printf(s_init, "#ifdef __cplusplus\n"); - Printf(s_init, "}\n"); - Printf(s_init, "#endif\n\n"); + SwigPHP_emit_resource_registrations(); + + /* start the init section */ + { + String * s_init_old = s_init; + s_init = NewString("/* init section */\n"); + Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n", NIL); + Printf(s_init, " STANDARD_MODULE_HEADER,\n"); + Printf(s_init, " \"%s\",\n", module); + Printf(s_init, " %s_functions,\n", module); + Printf(s_init, " PHP_MINIT(%s),\n", module); + if (Len(s_shutdown) > 0) { + Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module); + } else { + Printf(s_init, " NULL, /* No MSHUTDOWN code */\n"); + } + if (Len(r_init) > 0 || Len(s_vinit) > 0) { + Printf(s_init, " PHP_RINIT(%s),\n", module); + } else { + Printf(s_init, " NULL, /* No RINIT code */\n"); + } + if (Len(r_shutdown) > 0) { + Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module); + } else { + Printf(s_init, " NULL, /* No RSHUTDOWN code */\n"); + } + if (Len(pragma_phpinfo) > 0) { + Printf(s_init, " PHP_MINFO(%s),\n", module); + } else { + Printf(s_init, " NULL, /* No MINFO code */\n"); + } + if (Len(pragma_version) > 0) { + Printf(s_init, " \"%s\",\n", pragma_version); + } else { + Printf(s_init, " NO_VERSION_YET,\n"); + } + Printf(s_init, " STANDARD_MODULE_PROPERTIES\n"); + Printf(s_init, "};\n"); + Printf(s_init, "zend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", module); + + Printf(s_init, "#ifdef __cplusplus\n"); + Printf(s_init, "extern \"C\" {\n"); + Printf(s_init, "#endif\n"); + // We want to write "SWIGEXPORT ZEND_GET_MODULE(%s)" but ZEND_GET_MODULE + // in PHP7 has "extern "C" { ... }" around it so we can't do that. + Printf(s_init, "SWIGEXPORT zend_module_entry *get_module(void) { return &%s_module_entry; }\n", module); + Printf(s_init, "#ifdef __cplusplus\n"); + Printf(s_init, "}\n"); + Printf(s_init, "#endif\n\n"); + + Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n\n", module); + + Printv(s_init, s_init_old, NIL); + Delete(s_init_old); + } /* We have to register the constants before they are (possibly) used * by the pointer typemaps. This all needs re-arranging really as * things are being called in the wrong order */ - Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n", module); - /* Emit all of the code */ - Language::top(n); - - SwigPHP_emit_resource_registrations(); // Printv(s_init,s_resourcetypes,NIL); /* We need this after all classes written out by ::top */ - Printf(s_oinit, "CG(active_class_entry) = NULL;\n"); - Printf(s_oinit, "/* end oinit subsection */\n"); + Printf(s_oinit, " CG(active_class_entry) = NULL;\n"); + Printf(s_oinit, " /* end oinit subsection */\n"); Printf(s_init, "%s\n", s_oinit); /* Constants generated during top call */ - Printf(s_cinit, "/* end cinit subsection */\n"); + Printf(s_cinit, " /* end cinit subsection */\n"); Printf(s_init, "%s\n", s_cinit); Clear(s_cinit); Delete(s_cinit); - Printf(s_init, " return SUCCESS;\n"); + Printf(s_init, " return SUCCESS;\n"); Printf(s_init, "}\n\n"); // Now do REQUEST init which holds any user specified %rinit, and also vinit - Printf(s_init, "PHP_RINIT_FUNCTION(%s)\n{\n", module); - Printf(s_init, "%s\n", r_init); + if (Len(r_init) > 0 || Len(s_vinit) > 0) { + Printf(f_h, "PHP_RINIT_FUNCTION(%s);\n", module); - /* finish our init section which will have been used by class wrappers */ - Printf(s_vinit, "/* end vinit subsection */\n"); - Printf(s_init, "%s\n", s_vinit); - Clear(s_vinit); - Delete(s_vinit); + Printf(s_init, "PHP_RINIT_FUNCTION(%s)\n{\n", module); + if (Len(r_init) > 0) { + Printv(s_init, + "/* rinit section */\n", + r_init, "\n", + NIL); + } - Printf(s_init, " return SUCCESS;\n"); - Printf(s_init, "}\n\n"); + if (Len(s_vinit) > 0) { + /* finish our init section which will have been used by class wrappers */ + Printv(s_init, + " /* vinit subsection */\n", + s_vinit, "\n" + " /* end vinit subsection */\n", + NIL); + Clear(s_vinit); + } + Delete(s_vinit); - Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n" - "{\n", - s_shutdown, - "#ifdef ZTS\n" - " ts_free_id(", module, "_globals_id);\n" - "#endif\n" - " return SUCCESS;\n" - "}\n\n", NIL); + Printf(s_init, " return SUCCESS;\n"); + Printf(s_init, "}\n\n"); + } - Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module); - Printf(s_init, "%s\n", r_shutdown); - Printf(s_init, " return SUCCESS;\n"); - Printf(s_init, "}\n\n"); + Printf(f_h, "PHP_MINIT_FUNCTION(%s);\n", module); + + if (Len(s_shutdown) > 0) { + Printf(f_h, "PHP_MSHUTDOWN_FUNCTION(%s);\n", module); + + Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n" + "/* shutdown section */\n" + "{\n", + s_shutdown, + " return SUCCESS;\n" + "}\n\n", NIL); + } + + if (Len(r_shutdown) > 0) { + Printf(f_h, "PHP_RSHUTDOWN_FUNCTION(%s);\n", module); + + Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module); + Printf(s_init, "/* rshutdown section */\n"); + Printf(s_init, "%s\n", r_shutdown); + Printf(s_init, " return SUCCESS;\n"); + Printf(s_init, "}\n\n"); + } + + if (Len(pragma_phpinfo) > 0) { + Printf(f_h, "PHP_MINFO_FUNCTION(%s);\n", module); + + Printf(s_init, "PHP_MINFO_FUNCTION(%s)\n{\n", module); + Printf(s_init, "%s", pragma_phpinfo); + Printf(s_init, "}\n"); + } - Printf(s_init, "PHP_MINFO_FUNCTION(%s)\n{\n", module); - Printf(s_init, "%s", pragma_phpinfo); - Printf(s_init, "}\n"); Printf(s_init, "/* end init section */\n"); - Printf(f_h, "#endif /* PHP_%s_H */\n", cap_module); + Printf(f_h, "\n#endif /* PHP_%s_H */\n", cap_module); Delete(f_h); @@ -648,6 +666,7 @@ public: Delete(s_arginfo); Delete(f_runtime); Delete(f_begin); + Delete(arginfo_used); Printf(f_phpcode, "%s\n%s\n", pragma_incl, pragma_code); if (s_fakeoowrappers) { @@ -657,7 +676,7 @@ public: Delete(s_fakeoowrappers); s_fakeoowrappers = NULL; } - Printf(f_phpcode, "%s\n?>\n", s_phpclasses); + Printf(f_phpcode, "%s\n", s_phpclasses); Delete(f_phpcode); return SWIG_OK; @@ -667,22 +686,36 @@ public: void create_command(String *cname, String *iname, Node *n) { // This is for the single main zend_function_entry record Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname); - String * s = cs_entry; - if (!s) s = s_entry; - Printf(s, " SWIG_ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%(lower)s)\n", cname, iname, cname); - // This is the above referenced arginfo structure. + // We want to only emit each different arginfo once, as that reduces the + // size of both the generated source code and the compiled extension + // module. To do this, we name the arginfo to encode the number of + // parameters and which (if any) are passed by reference by using a + // sequence of 0s (for non-reference) and 1s (for by references). ParmList *l = Getattr(n, "parms"); - Printf(s_arginfo, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_%(lower)s, 0, 0, 0)\n", cname); + String * arginfo_code = NewStringEmpty(); for (Parm *p = l; p; p = Getattr(p, "tmap:in:next")) { /* Ignored parameters */ if (checkAttribute(p, "tmap:in:numinputs", "0")) { continue; } - int byref = GetFlag(p, "tmap:in:byref"); - Printf(s_arginfo, " ZEND_ARG_PASS_INFO(%d)\n", byref); + Append(arginfo_code, GetFlag(p, "tmap:in:byref") ? "1" : "0"); } - Printf(s_arginfo, "ZEND_END_ARG_INFO()\n"); + + if (!GetFlag(arginfo_used, arginfo_code)) { + // Not had this one before, so emit it. + SetFlag(arginfo_used, arginfo_code); + Printf(s_arginfo, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_%s, 0, 0, 0)\n", arginfo_code); + for (const char * p = Char(arginfo_code); *p; ++p) { + Printf(s_arginfo, " ZEND_ARG_PASS_INFO(%c)\n", *p); + } + Printf(s_arginfo, "ZEND_END_ARG_INFO()\n"); + } + + String * s = cs_entry; + if (!s) s = s_entry; + Printf(s, " SWIG_ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%s)\n", cname, iname, arginfo_code); + Delete(arginfo_code); } /* ------------------------------------------------------------ @@ -710,12 +743,12 @@ public: Wrapper_add_local(f, "argc", "int argc"); - Printf(tmp, "zval **argv[%d]", maxargs); + Printf(tmp, "zval argv[%d]", maxargs); Wrapper_add_local(f, "argv", tmp); Printf(f->code, "argc = ZEND_NUM_ARGS();\n"); - Printf(f->code, "zend_get_parameters_array_ex(argc,argv);\n"); + Printf(f->code, "zend_get_parameters_array_ex(argc, argv);\n"); Replaceall(dispatch, "$args", "self,args"); @@ -723,7 +756,7 @@ public: Printf(f->code, "SWIG_ErrorCode() = E_ERROR;\n"); Printf(f->code, "SWIG_ErrorMsg() = \"No matching function for overloaded '%s'\";\n", symname); - Printv(f->code, "SWIG_FAIL(TSRMLS_C);\n", NIL); + Printv(f->code, "SWIG_FAIL();\n", NIL); Printv(f->code, "}\n", NIL); Wrapper_print(f, s_wrappers); @@ -819,8 +852,8 @@ public: if (num_arguments > 0) { String *args = NewStringEmpty(); if (wrapperType == directorconstructor) - Wrapper_add_local(f, "arg0", "zval *arg0"); - Printf(args, "zval **args[%d]", num_arguments); + Wrapper_add_local(f, "arg0", "zval * arg0"); + Printf(args, "zval args[%d]", num_arguments); Wrapper_add_local(f, "args", args); Delete(args); args = NULL; @@ -834,7 +867,7 @@ public: // NOTE: possible we ignore this_ptr as a param for native constructor - Printf(f->code, "SWIG_ResetError(TSRMLS_C);\n"); + Printf(f->code, "SWIG_ResetError();\n"); if (numopt > 0) { // membervariable wrappers do not have optional args Wrapper_add_local(f, "arg_count", "int arg_count"); @@ -851,7 +884,7 @@ public: Printf(f->code, "WRONG_PARAM_COUNT;\n}\n\n"); } if (wrapperType == directorconstructor) - Printf(f->code, "arg0 = *args[0];\n \n"); + Printf(f->code, "arg0 = &args[0];\n \n"); /* Now convert from PHP to C variables */ // At this point, argcount if used is the number of deliberately passed args @@ -891,7 +924,7 @@ public: } if ((tm = Getattr(p, "tmap:in"))) { - Replaceall(tm, "$source", source); + Replaceall(tm, "$source", &source); Replaceall(tm, "$target", ln); Replaceall(tm, "$input", source); Setattr(p, "emit:input", source); @@ -915,7 +948,7 @@ public: if (is_member_director(n)) { Wrapper_add_local(f, "upcall", "bool upcall = false"); - Printf(f->code, "upcall = !Swig::Director::swig_is_overridden_method((char *)\"%s%s\", (char *)\"%s\" TSRMLS_CC);\n", + Printf(f->code, "upcall = !Swig::Director::swig_is_overridden_method(\"%s%s\", \"%s\");\n", prefix, Swig_class_name(Swig_methodclass(n)), name); } @@ -946,7 +979,7 @@ public: /* Insert argument output code */ bool hasargout = false; for (i = 0, p = l; p; i++) { - if ((tm = Getattr(p, "tmap:argout"))) { + if ((tm = Getattr(p, "tmap:argout")) && Len(tm)) { hasargout = true; Replaceall(tm, "$source", Getattr(p, "lname")); // Replaceall(tm,"$input",Getattr(p,"lname")); @@ -1000,12 +1033,13 @@ public: Delete(tm); } + Printf(f->code, "thrown:\n"); Printf(f->code, "return;\n"); /* Error handling code */ Printf(f->code, "fail:\n"); Printv(f->code, cleanup, NIL); - Append(f->code, "SWIG_FAIL(TSRMLS_C);\n"); + Append(f->code, "SWIG_FAIL();\n"); Printf(f->code, "}\n"); @@ -1055,17 +1089,18 @@ public: bool handle_as_overload = false; String **arg_names; String **arg_values; + unsigned char * byref; // Method or static method or plain function. const char *methodname = 0; String *output = s_oowrappers; if (constructor) { class_has_ctor = true; // Skip the Foo:: prefix. - char *ptr = strrchr(GetChar(Swig_methodclass(n), "sym:name"), ':'); + char *ptr = strrchr(GetChar(current_class, "sym:name"), ':'); if (ptr) { ptr++; } else { - ptr = GetChar(Swig_methodclass(n), "sym:name"); + ptr = GetChar(current_class, "sym:name"); } if (strcmp(ptr, GetChar(n, "constructorHandler:sym:name")) == 0) { methodname = "__construct"; @@ -1195,7 +1230,8 @@ public: } arg_values = (String **) malloc(max_num_of_arguments * sizeof(String *)); - if (!arg_values) { + byref = (unsigned char *) malloc(max_num_of_arguments); + if (!arg_values || !byref) { /* FIXME: How should this be handled? The rest of SWIG just seems * to not bother checking for malloc failing! */ fprintf(stderr, "Malloc failed!\n"); @@ -1203,6 +1239,7 @@ public: } for (i = 0; i < max_num_of_arguments; ++i) { arg_values[i] = NULL; + byref[i] = false; } Node *o; @@ -1222,6 +1259,7 @@ public: continue; } assert(0 <= argno && argno < max_num_of_arguments); + byref[argno] = GetFlag(p, "tmap:in:byref"); String *&pname = arg_names[argno]; const char *pname_cstr = GetChar(p, "name"); // Just get rid of the C++ namespace part for now. @@ -1424,14 +1462,6 @@ public: /* We need $this to refer to the current class, so can't allow it * to be used as a parameter. */ Setattr(seen, "this", seen); - /* We use $r to store the return value, so disallow that as a parameter - * name in case the user uses the "call-time pass-by-reference" feature - * (it's deprecated and off by default in PHP5, but we want to be - * maximally portable). Similarly we use $c for the classname or new - * stdClass object. - */ - Setattr(seen, "r", seen); - Setattr(seen, "c", seen); for (int argno = 0; argno < max_num_of_arguments; ++argno) { String *&pname = arg_names[argno]; @@ -1470,6 +1500,7 @@ public: Printf(args, ","); if (i || wrapperType == memberfn) Printf(invoke, ","); + if (byref[i]) Printf(args, "&"); String *value = arg_values[i]; if (value) { const char *v = Char(value); @@ -1478,6 +1509,9 @@ public: Replaceall(value, "$", "\\$"); } Printf(args, "$%s=%s", arg_names[i], value); + } else if (constructor && strcmp(methodname, "__construct") == 0 && i >= 1 && i < min_num_of_arguments) { + // We need to be able to call __construct($resource). + Printf(args, "$%s=null", arg_names[i]); } else { Printf(args, "$%s", arg_names[i]); } @@ -1498,6 +1532,15 @@ public: Printf(invoke_args, ","); } Printf(invoke_args, "%s", args); + if (constructor && min_num_of_arguments > 1) { + // We need to be able to call __construct($resource). + Clear(args); + Printf(args, "$%s", arg_names[0]); + for (i = 1; i < min_num_of_arguments; ++i) { + Printf(args, ","); + Printf(args, "$%s=null", arg_names[i]); + } + } bool had_a_case = false; int last_handled_i = i - 1; for (; i < max_num_of_arguments; ++i) { @@ -1523,13 +1566,15 @@ public: Printf(prepare, "case %d: ", ++last_handled_i); } if (non_void_return) { - if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) { + if ((!directorsEnabled() || !Swig_directorclass(n)) && !constructor) { + Append(prepare, "$r="); + } else if (wrapperType == staticmemberfn || wrapperType == staticmembervar) { Append(prepare, "$r="); } else { Printf(prepare, "$this->%s=", SWIG_PTR); } } - if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) { + if (!directorsEnabled() || !Swig_directorclass(n) || !constructor) { Printf(prepare, "%s(%s); break;\n", iname, invoke_args); } else if (!i) { Printf(prepare, "%s($_this%s); break;\n", iname, invoke_args); @@ -1545,14 +1590,16 @@ public: if (had_a_case) Printf(prepare, "default: "); if (non_void_return) { - if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) { + if ((!directorsEnabled() || !Swig_directorclass(n)) && !constructor) { + Append(prepare, "$r="); + } else if (wrapperType == staticmemberfn || wrapperType == staticmembervar) { Append(prepare, "$r="); } else { Printf(prepare, "$this->%s=", SWIG_PTR); } } - if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) { + if (!directorsEnabled() || !Swig_directorclass(n) || !constructor) { Printf(prepare, "%s(%s);\n", iname, invoke_args); } else { Printf(prepare, "%s($_this, %s);\n", iname, invoke_args); @@ -1620,20 +1667,33 @@ public: } if (constructor) { - const char * arg0; + // Discriminate between the PHP constructor and a C++ constructor + // renamed to become a factory function in PHP. + bool php_constructor = (strcmp(methodname, "__construct") == 0); + const char * arg0 = NULL; if (max_num_of_arguments > 0) { arg0 = Char(arg_names[0]); - } else { + } else if (php_constructor) { + // The PHP constructor needs to be able to wrap a resource, but a + // renamed constructor doesn't. arg0 = "res"; Delete(args); args = NewString("$res=null"); } String *mangled_type = SwigType_manglestr(Getattr(n, "type")); + if (!php_constructor) { + // A renamed constructor should be a static method. + Append(acc, "static "); + } Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args); - Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '%s') {\n", arg0, arg0, mangled_type); - Printf(output, "\t\t\t$this->%s=$%s;\n", SWIG_PTR, arg0); - Printf(output, "\t\t\treturn;\n"); - Printf(output, "\t\t}\n"); + if (php_constructor) { + // The PHP constructor needs to be able to wrap a resource, but a + // renamed constructor doesn't. + Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '%s') {\n", arg0, arg0, mangled_type); + Printf(output, "\t\t\t$this->%s=$%s;\n", SWIG_PTR, arg0); + Printf(output, "\t\t\treturn;\n"); + Printf(output, "\t\t}\n"); + } } else { Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args); } @@ -1662,7 +1722,7 @@ public: Printf(output, "\tstatic function %s(%s) {\n", methodname, args); } - if (!newobject) + if (!constructor) Printf(output, "%s", prepare); if (constructor) { if (!directorsEnabled() || !Swig_directorclass(n)) { @@ -1790,7 +1850,7 @@ public: Delete(wrapobj); } } else { - if (non_void_return) { + if (non_void_return || hasargout) { Printf(output, "\t\treturn %s;\n", invoke); } else if (Cmp(invoke, "$r") != 0) { Printf(output, "\t\t%s;\n", invoke); @@ -1949,7 +2009,7 @@ done: String *type = Getattr(n, "name"); String *value = Getattr(n, "value"); - if (Strcmp(lang, "php") == 0 || Strcmp(lang, "php4") == 0) { + if (Strcmp(lang, "php") == 0) { if (Strcmp(type, "code") == 0) { if (value) { Printf(pragma_code, "%s\n", value); @@ -1962,6 +2022,10 @@ done: if (value) { Printf(pragma_phpinfo, "%s\n", value); } + } else if (Strcmp(type, "version") == 0) { + if (value) { + pragma_version = value; + } } else { Swig_warning(WARN_PHP_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", type); } @@ -2148,7 +2212,6 @@ done: } Printf(s_phpclasses, "\t}\n"); - /* Create __isset for PHP 5.1 and later; PHP 5.0 will just ignore it. */ /* __isset() should return true for read-only properties, so check for * *_get() not *_set(). */ Printf(s_phpclasses, "\n\tfunction __isset($var) {\n"); @@ -2289,15 +2352,15 @@ done: Delete(director_ctor_code); director_ctor_code = NewStringEmpty(); director_prot_ctor_code = NewStringEmpty(); - Printf(director_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n"); - Printf(director_prot_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n"); + Printf(director_ctor_code, "if (Z_TYPE_P(arg0) == IS_NULL) { /* not subclassed */\n"); + Printf(director_prot_ctor_code, "if (Z_TYPE_P(arg0) == IS_NULL) { /* not subclassed */\n"); Printf(director_ctor_code, " %s = (%s *)new %s(%s);\n", Swig_cresult_name(), ctype, ctype, args); Printf(director_prot_ctor_code, " SWIG_PHP_Error(E_ERROR, \"accessing abstract class or protected constructor\");\n", name, name, args); if (i) { Insert(args, 0, ", "); } - Printf(director_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0 TSRMLS_CC%s);\n}\n", Swig_cresult_name(), ctype, sname, args); - Printf(director_prot_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0 TSRMLS_CC%s);\n}\n", Swig_cresult_name(), ctype, sname, args); + Printf(director_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0%s);\n}\n", Swig_cresult_name(), ctype, sname, args); + Printf(director_prot_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0%s);\n}\n", Swig_cresult_name(), ctype, sname, args); Delete(args); wrapperType = directorconstructor; @@ -2327,9 +2390,9 @@ done: Wrapper *f = NewWrapper(); Printf(f->def, "/* This function is designed to be called by the zend list destructors */\n"); Printf(f->def, "/* to typecast and do the actual destruction */\n"); - Printf(f->def, "static void %s(zend_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {\n", destructorname); + Printf(f->def, "static void %s(zend_resource *res, const char *type_name) {\n", destructorname); - Wrapper_add_localv(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr", NIL); + Wrapper_add_localv(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) res->ptr", NIL); Wrapper_add_localv(f, "ptr", "void *ptr=value->ptr", NIL); Wrapper_add_localv(f, "newobject", "int newobject=value->newobject", NIL); @@ -2347,7 +2410,7 @@ done: Printf(f->code, " efree(value);\n"); Printf(f->code, " if (! newobject) return; /* can't delete it! */\n"); - Printf(f->code, " arg1 = (%s)SWIG_ZTS_ConvertResourceData(ptr,type_name,SWIGTYPE%s TSRMLS_CC);\n", SwigType_lstr(pt, 0), SwigType_manglestr(pt)); + Printf(f->code, " arg1 = (%s)SWIG_ConvertResourceData(ptr, type_name, SWIGTYPE%s);\n", SwigType_lstr(pt, 0), SwigType_manglestr(pt)); Printf(f->code, " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n", Char(name)); Setattr(n, "wrap:name", destructorname); @@ -2356,9 +2419,10 @@ done: Append(f->code, actioncode); Delete(actioncode); + Printf(f->code, "thrown:\n"); Append(f->code, "return;\n"); Append(f->code, "fail:\n"); - Append(f->code, "SWIG_FAIL(TSRMLS_C);\n"); + Append(f->code, "SWIG_FAIL();\n"); Printf(f->code, "}\n"); Wrapper_print(f, s_wrappers); @@ -2418,16 +2482,9 @@ done: String *call; String *basetype = Getattr(parent, "classtype"); - // We put TSRMLS_DC after the self parameter in order to cope with - // any default parameters. - String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); - const char * p = Char(target); - const char * comma = strchr(p, ','); - int ins = comma ? (int)(comma - p) : Len(target) - 1; - Insert(target, ins, " TSRMLS_DC"); - + String *target = Swig_method_decl(0, decl, classname, parms, 0); call = Swig_csuperclass_call(0, basetype, superparms); - Printf(w->def, "%s::%s: %s, Swig::Director(self TSRMLS_CC) {", classname, target, call); + Printf(w->def, "%s::%s: %s, Swig::Director(self) {", classname, target, call); Append(w->def, "}"); Delete(target); Wrapper_print(w, f_directors); @@ -2437,14 +2494,7 @@ done: /* constructor header */ { - // We put TSRMLS_DC after the self parameter in order to cope with - // any default parameters. - String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); - const char * p = Char(target); - const char * comma = strchr(p, ','); - int ins = comma ? (int)(comma - p) : Len(target) - 1; - Insert(target, ins, " TSRMLS_DC"); - + String *target = Swig_method_decl(0, decl, classname, parms, 1); Printf(f_directors_h, " %s;\n", target); Delete(target); } @@ -2488,16 +2538,20 @@ done: String *pclassname = NewStringf("SwigDirector_%s", classname); String *qualified_name = NewStringf("%s::%s", pclassname, name); SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); - target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); + target = Swig_method_decl(rtype, decl, qualified_name, l, 0); Printf(w->def, "%s", target); Delete(qualified_name); Delete(target); /* header declaration */ - target = Swig_method_decl(rtype, decl, name, l, 0, 1); + target = Swig_method_decl(rtype, decl, name, l, 1); Printf(declaration, " virtual %s", target); Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { @@ -2529,14 +2583,20 @@ done: Append(w->def, " {"); Append(declaration, ";\n"); - Printf(w->code, "TSRMLS_FETCH_FROM_CTX(swig_zts_ctx);\n"); - /* declare method return value * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { String *cres = SwigType_lstr(returntype, "c_result"); Printf(w->code, "%s;\n", cres); Delete(cres); @@ -2551,7 +2611,7 @@ done: Printf(w->code, "%s;\n", super_call); Delete(super_call); } else { - Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\" TSRMLS_CC);\n", SwigType_namestr(c_classname), + Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); } } else { @@ -2562,11 +2622,10 @@ done: /* remove the wrapper 'w' since it was producing spurious temps */ Swig_typemap_attach_parms("in", l, 0); - Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorin", l, w); Swig_typemap_attach_parms("directorargout", l, w); Parm *p; - char source[256]; int outputs = 0; if (!is_void) @@ -2590,16 +2649,11 @@ done: if ((tm = Getattr(p, "tmap:directorin")) != 0) { String *parse = Getattr(p, "tmap:directorin:parse"); if (!parse) { - sprintf(source, "obj%d", idx++); - String *input = NewStringf("&%s", source); + String *input = NewStringf("&args[%d]", idx++); Setattr(p, "emit:directorinput", input); Replaceall(tm, "$input", input); Delete(input); Replaceall(tm, "$owner", "0"); - Printv(wrap_args, "zval ", source, ";\n", NIL); - Printf(wrap_args, "args[%d] = &%s;\n", idx - 1, source); - Printv(wrap_args, "INIT_ZVAL(", source, ");\n", NIL); - Printv(wrap_args, tm, "\n", NIL); Putc('O', parse_args); } else { @@ -2623,6 +2677,7 @@ done: } /* exception handling */ + bool error_used_in_typemap = false; tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0); if (!tm) { tm = Getattr(n, "feature:director:except"); @@ -2632,6 +2687,7 @@ done: if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) { if (Replaceall(tm, "$error", "error")) { /* Only declare error if it is used by the typemap. */ + error_used_in_typemap = true; Append(w->code, "int error;\n"); } } else { @@ -2640,23 +2696,26 @@ done: } if (!idx) { - Printf(w->code, "zval **args = NULL;\n"); + Printf(w->code, "zval *args = NULL;\n"); } else { - Printf(w->code, "zval *args[%d];\n", idx); + Printf(w->code, "zval args[%d];\n", idx); } - Printf(w->code, "zval *%s, funcname;\n", Swig_cresult_name()); - Append(w->code, "if (!swig_self) {\n"); - Append(w->code, " SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");"); - Append(w->code, "}\n\n"); - Printf(w->code, "MAKE_STD_ZVAL(%s);\n", Swig_cresult_name()); + // typemap_directorout testcase requires that 0 can be assigned to the + // variable named after the result of Swig_cresult_name(), so that can't + // be a zval - make it a pointer to one instead. + Printf(w->code, "zval swig_zval_result, swig_funcname;\n", Swig_cresult_name()); + Printf(w->code, "zval * SWIGUNUSED %s = &swig_zval_result;\n", Swig_cresult_name()); const char * funcname = GetChar(n, "sym:name"); - Printf(w->code, "ZVAL_STRINGL(&funcname, (char *)\"%s\", %d, 0);\n", funcname, strlen(funcname)); + Printf(w->code, "ZVAL_STRINGL(&swig_funcname, \"%s\", %d);\n", funcname, strlen(funcname)); /* wrap complex arguments to zvals */ Printv(w->code, wrap_args, NIL); - Append(w->code, "call_user_function(EG(function_table), (zval**)&swig_self, &funcname,"); - Printf(w->code, " %s, %d, args TSRMLS_CC);\n", Swig_cresult_name(), idx); + if (error_used_in_typemap) { + Append(w->code, "error = "); + } + Append(w->code, "call_user_function(EG(function_table), &swig_self, &swig_funcname,"); + Printf(w->code, " &swig_zval_result, %d, args);\n", idx); if (tm) { Printv(w->code, Str(tm), "\n", NIL); @@ -2708,13 +2767,12 @@ done: } } - Printf(w->code, "FREE_ZVAL(%s);\n", Swig_cresult_name()); - Delete(parse_args); Delete(cleanup); Delete(outarg); } + Append(w->code, "thrown:\n"); if (!is_void) { if (!(ignored_method && !pure_virtual)) { String *rettype = SwigType_str(returntype, 0); @@ -2730,7 +2788,7 @@ done: } Append(w->code, "fail:\n"); - Append(w->code, "SWIG_FAIL(TSRMLS_C);\n"); + Append(w->code, "SWIG_FAIL();\n"); Append(w->code, "}\n"); // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method @@ -2775,7 +2833,8 @@ static PHP *maininstance = 0; // We use this function to be able to write out zend_register_list_destructor_ex // lines for most things in the type table // NOTE: it's a function NOT A PHP::METHOD -extern "C" void typetrace(const SwigType *ty, String *mangled, String *clientdata) { +extern "C" { +static void typetrace(const SwigType *ty, String *mangled, String *clientdata) { Node *class_node; if (!zend_types) { zend_types = NewHash(); @@ -2795,6 +2854,7 @@ extern "C" void typetrace(const SwigType *ty, String *mangled, String *clientdat if (r_prevtracefunc) (*r_prevtracefunc) (ty, mangled, (String *) clientdata); } +} /* ----------------------------------------------------------------------------- * new_swig_php() - Instantiate module @@ -2811,13 +2871,6 @@ static Language *new_swig_php() { return maininstance; } -extern "C" Language *swig_php4(void) { - Printf(stderr, "*** -php4 is no longer supported.\n" - "*** Either upgrade to PHP5 or use SWIG 1.3.36 or earlier.\n"); - SWIG_exit(EXIT_FAILURE); - return NULL; // To avoid compiler warnings. -} - extern "C" Language *swig_php(void) { return new_swig_php(); } diff --git a/Source/Modules/pike.cxx b/Source/Modules/pike.cxx index 6a74851c8..b8ed4037a 100644 --- a/Source/Modules/pike.cxx +++ b/Source/Modules/pike.cxx @@ -261,10 +261,9 @@ public: rename = strip(name); Printf(f_classInit, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description); break; - case CLASS_CONST: - assert(false); // shouldn't have gotten here for CLASS_CONST nodes - default: - assert(false); // what is this? + case CLASS_CONST: // shouldn't have gotten here for CLASS_CONST nodes + default: // what is this? + assert(false); } Delete(rename); } diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index fbae8f480..39308d4b8 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * This file is part of SWIG, which is licensed as a whole under version 3 + * This file is part of SWIG, which is licensed as a whole under version 3 * (or any later version) of the GNU General Public License. Some additional * terms also apply to certain portions of SWIG. The full details of the SWIG * license and copyrights can be found in the LICENSE and COPYRIGHT files @@ -17,10 +17,16 @@ #include #include #include +#include "pydoc.h" + +#include #define PYSHADOW_MEMBER 0x2 #define WARN_PYTHON_MULTIPLE_INH 405 +#define PYTHON_INT_MAX (2147483647) +#define PYTHON_INT_MIN (-2147483647-1) + static String *const_code = 0; static String *module = 0; static String *package = 0; @@ -44,22 +50,22 @@ static File *f_shadow_py = 0; static String *f_shadow = 0; static String *f_shadow_begin = 0; static Hash *f_shadow_imports = 0; -static String *f_shadow_builtin_imports = 0; +static String *f_shadow_after_begin = 0; static String *f_shadow_stubs = 0; static Hash *builtin_getset = 0; +static Hash *builtin_closures = 0; static Hash *class_members = 0; static File *f_builtins = 0; static String *builtin_tp_init = 0; static String *builtin_methods = 0; static String *builtin_default_unref = 0; +static String *builtin_closures_code = 0; static String *methods; +static String *methods_proxydocs; static String *class_name; static String *shadow_indent = 0; static int in_class = 0; -static int classic = 0; -static int modern = 0; -static int new_repr = 1; static int no_header_file = 0; static int max_bases = 0; static int builtin_bases_needed = 0; @@ -75,24 +81,15 @@ static String *real_classname; /* Thread Support */ static int threads = 0; static int nothreads = 0; -static int classptr = 0; + /* Other options */ -static int shadowimport = 1; -static int buildnone = 0; -static int nobuildnone = 0; -static int safecstrings = 0; static int dirvtable = 0; -static int proxydel = 1; -static int fastunpack = 0; +static int doxygen = 0; +static int fastunpack = 1; static int fastproxy = 0; -static int fastquery = 0; -static int fastinit = 0; static int olddefs = 0; -static int modernargs = 0; -static int aliasobj0 = 0; static int castmode = 0; static int extranative = 0; -static int outputtuple = 0; static int nortti = 0; static int relativeimport = 0; @@ -103,68 +100,38 @@ enum autodoc_t { AUTODOC_DTOR, AUTODOC_STATICFUNC, AUTODOC_FUNC, - AUTODOC_METHOD + AUTODOC_METHOD, + AUTODOC_CONST, + AUTODOC_VAR }; static const char *usage1 = "\ Python Options (available with -python)\n\ - -aliasobj0 - Alias obj0 when using fastunpack, needed for some old typemaps \n\ - -buildnone - Use Py_BuildValue(" ") to obtain Py_None (default in Windows)\n\ - -builtin - Create new python built-in types, rather than proxy classes, for better performance\n\ - -castmode - Enable the casting mode, which allows implicit cast between types in python\n\ - -classic - Use classic classes only\n\ - -classptr - Generate shadow 'ClassPtr' as in older swig versions\n\ - -cppcast - Enable C++ casting operators (default) \n\ - -dirvtable - Generate a pseudo virtual table for directors for faster dispatch \n\ - -extranative - Return extra native C++ wraps for std containers when possible \n\ - -fastinit - Use fast init mechanism for classes (default)\n\ - -fastunpack - Use fast unpack mechanism to parse the argument functions \n\ - -fastproxy - Use fast proxy mechanism for member methods \n\ - -fastquery - Use fast query mechanism for types \n\ - -globals - Set used to access C global variable [default: 'cvar']\n\ - -interface - Set the lib name to \n\ - -keyword - Use keyword arguments\n\ - -modern - Use modern python features only, without compatibility code\n\ - -modernargs - Use \"modern\" args mechanism to pack/unpack the function arguments\n"; + -builtin - Create Python built-in types rather than proxy classes, for better performance\n\ + -castmode - Enable the casting mode, which allows implicit cast between types in Python\n\ + -debug-doxygen-parser - Display doxygen parser module debugging information\n\ + -debug-doxygen-translator - Display doxygen translator module debugging information\n\ + -dirvtable - Generate a pseudo virtual table for directors for faster dispatch\n\ + -doxygen - Convert C++ doxygen comments to pydoc comments in proxy classes\n\ + -extranative - Return extra native wrappers for C++ std containers wherever possible\n\ + -fastproxy - Use fast proxy mechanism for member methods\n\ + -globals - Set used to access C global variable (default: 'cvar')\n\ + -interface - Set low-level C/C++ module name to (default: module name prefixed by '_')\n\ + -keyword - Use keyword arguments\n"; static const char *usage2 = "\ - -newrepr - Use more informative version of __repr__ in proxy classes (default) \n\ - -newvwm - New value wrapper mode, use only when everything else fails \n\ - -noaliasobj0 - Don't generate an obj0 alias when using fastunpack (default) \n\ - -nobuildnone - Access Py_None directly (default in non-Windows systems)\n\ - -nocastmode - Disable the casting mode (default)\n\ - -nocppcast - Disable C++ casting operators, useful for generating bugs\n\ - -nodirvtable - Don't use the virtual table feature, resolve the python method each time (default)\n\ - -noexcept - No automatic exception handling\n\ - -noextranative - Don't use extra native C++ wraps for std containers when possible (default) \n\ - -nofastinit - Use traditional init mechanism for classes \n\ - -nofastunpack - Use traditional UnpackTuple method to parse the argument functions (default) \n\ - -nofastproxy - Use traditional proxy mechanism for member methods (default) \n\ - -nofastquery - Use traditional query mechanism for types (default) \n\ - -noh - Don't generate the output header file\n\ - -nomodern - Don't use modern python features which are not backwards compatible \n\ - -nomodernargs - Use classic ParseTuple/CallFunction methods to pack/unpack the function arguments (default) \n"; + -nofastunpack - Use traditional UnpackTuple method to parse the argument functions\n\ + -noh - Don't generate the output header file\n"; static const char *usage3 = "\ - -noolddefs - Don't emit the old method definitions even when using fastproxy (default) \n\ - -nooutputtuple - Use a PyList for appending output values (default) \n\ - -noproxy - Don't generate proxy classes \n\ - -noproxydel - Don't generate the redundant __del__ method \n\ - -noproxyimport - Don't insert proxy import statements derived from the %import directive \n\ + -noproxy - Don't generate proxy classes\n\ -nortti - Disable the use of the native C++ RTTI with directors\n\ - -nosafecstrings - Avoid extra strings copies when possible (default)\n\ -nothreads - Disable thread support for the entire interface\n\ - -olddefs - Keep the old method definitions even when using fastproxy\n\ - -oldrepr - Use shorter and old version of __repr__ in proxy classes\n\ - -outputtuple - Use a PyTuple for outputs instead of a PyList (use carefully with legacy interfaces) \n\ - -proxydel - Generate a __del__ method even though it is now redundant (default) \n\ - -relativeimport - Use relative python imports \n\ - -safecstrings - Use safer (but slower) C string mapping, generating copies from Python -> C/C++\n\ + -olddefs - Keep the old method definitions when using -fastproxy\n\ + -py3 - Generate code with Python 3 specific features and syntax\n\ + -relativeimport - Use relative Python imports\n\ -threads - Add thread support for all the interface\n\ - -O - Enable the following optimization options: \n\ - -modern -fastdispatch -nosafecstrings -fvirtual -noproxydel \n\ - -fastproxy -fastinit -fastunpack -fastquery -modernargs -nobuildnone \n\ - -py3 - Generate code with Python 3 specific features:\n\ - Function annotation \n\ + -O - Enable the following optimization options:\n\ + -fastdispatch -fastproxy -fvirtual\n\ \n"; static String *getSlot(Node *n = NULL, const char *key = NULL, String *default_slot = NULL) { @@ -175,7 +142,7 @@ static String *getSlot(Node *n = NULL, const char *key = NULL, String *default_s static void printSlot(File *f, String *slotval, const char *slotname, const char *functype = NULL) { String *slotval_override = 0; - if (functype) + if (functype && Strcmp(slotval, "0") == 0) slotval = slotval_override = NewStringf("(%s) %s", functype, slotval); int len = Len(slotval); int fieldwidth = len > 41 ? (len > 61 ? 0 : 61 - len) : 41 - len; @@ -188,7 +155,7 @@ static String *getClosure(String *functype, String *wrapper, int funpack = 0) { "unaryfunc", "SWIGPY_UNARYFUNC_CLOSURE", "destructor", "SWIGPY_DESTRUCTOR_CLOSURE", "inquiry", "SWIGPY_INQUIRY_CLOSURE", - "getiterfunc", "SWIGPY_UNARYFUNC_CLOSURE", + "getiterfunc", "SWIGPY_GETITERFUNC_CLOSURE", "binaryfunc", "SWIGPY_BINARYFUNC_CLOSURE", "ternaryfunc", "SWIGPY_TERNARYFUNC_CLOSURE", "ternarycallfunc", "SWIGPY_TERNARYCALLFUNC_CLOSURE", @@ -197,10 +164,11 @@ static String *getClosure(String *functype, String *wrapper, int funpack = 0) { "ssizessizeargfunc", "SWIGPY_SSIZESSIZEARGFUNC_CLOSURE", "ssizeobjargproc", "SWIGPY_SSIZEOBJARGPROC_CLOSURE", "ssizessizeobjargproc", "SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE", + "objobjproc", "SWIGPY_OBJOBJPROC_CLOSURE", "objobjargproc", "SWIGPY_OBJOBJARGPROC_CLOSURE", "reprfunc", "SWIGPY_REPRFUNC_CLOSURE", "hashfunc", "SWIGPY_HASHFUNC_CLOSURE", - "iternextfunc", "SWIGPY_ITERNEXT_CLOSURE", + "iternextfunc", "SWIGPY_ITERNEXTFUNC_CLOSURE", NULL }; @@ -208,7 +176,7 @@ static String *getClosure(String *functype, String *wrapper, int funpack = 0) { "unaryfunc", "SWIGPY_UNARYFUNC_CLOSURE", "destructor", "SWIGPY_DESTRUCTOR_CLOSURE", "inquiry", "SWIGPY_INQUIRY_CLOSURE", - "getiterfunc", "SWIGPY_UNARYFUNC_CLOSURE", + "getiterfunc", "SWIGPY_GETITERFUNC_CLOSURE", "ternaryfunc", "SWIGPY_TERNARYFUNC_CLOSURE", "ternarycallfunc", "SWIGPY_TERNARYCALLFUNC_CLOSURE", "lenfunc", "SWIGPY_LENFUNC_CLOSURE", @@ -216,10 +184,11 @@ static String *getClosure(String *functype, String *wrapper, int funpack = 0) { "ssizessizeargfunc", "SWIGPY_SSIZESSIZEARGFUNC_CLOSURE", "ssizeobjargproc", "SWIGPY_SSIZEOBJARGPROC_CLOSURE", "ssizessizeobjargproc", "SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE", + "objobjproc", "SWIGPY_FUNPACK_OBJOBJPROC_CLOSURE", "objobjargproc", "SWIGPY_OBJOBJARGPROC_CLOSURE", "reprfunc", "SWIGPY_REPRFUNC_CLOSURE", "hashfunc", "SWIGPY_HASHFUNC_CLOSURE", - "iternextfunc", "SWIGPY_ITERNEXT_CLOSURE", + "iternextfunc", "SWIGPY_ITERNEXTFUNC_CLOSURE", NULL }; @@ -253,6 +222,11 @@ public: director_multiple_inheritance = 1; director_language = 1; } + + ~PYTHON() { + delete doxygenTranslator; + } + /* ------------------------------------------------------------ * Thread Implementation * ------------------------------------------------------------ */ @@ -324,10 +298,11 @@ public: * ------------------------------------------------------------ */ virtual void main(int argc, char *argv[]) { - int cppcast = 1; SWIG_library_directory("python"); + int doxygen_translator_flags = 0; + for (int i = 1; i < argc; i++) { if (argv[i]) { if (strcmp(argv[i], "-interface") == 0) { @@ -352,42 +327,13 @@ public: } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) { shadow = 1; Swig_mark_arg(i); - } else if ((strcmp(argv[i], "-new_repr") == 0) || (strcmp(argv[i], "-newrepr") == 0)) { - new_repr = 1; - Swig_mark_arg(i); - } else if ((strcmp(argv[i], "-old_repr") == 0) || (strcmp(argv[i], "-oldrepr") == 0)) { - new_repr = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-classptr") == 0) { - classptr = 1; - Swig_mark_arg(i); } else if ((strcmp(argv[i], "-noproxy") == 0)) { shadow = 0; Swig_mark_arg(i); - } else if ((strcmp(argv[i], "-noproxyimport") == 0)) { - shadowimport = 0; - Swig_mark_arg(i); } else if (strcmp(argv[i], "-keyword") == 0) { use_kw = 1; SWIG_cparse_set_compact_default_args(1); Swig_mark_arg(i); - } else if (strcmp(argv[i], "-classic") == 0) { - classic = 1; - modernargs = 0; - modern = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-cppcast") == 0) { - cppcast = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nocppcast") == 0) { - cppcast = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-outputtuple") == 0) { - outputtuple = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nooutputtuple") == 0) { - outputtuple = 0; - Swig_mark_arg(i); } else if (strcmp(argv[i], "-nortti") == 0) { nortti = 1; Swig_mark_arg(i); @@ -395,31 +341,21 @@ public: threads = 1; Swig_mark_arg(i); } else if (strcmp(argv[i], "-nothreads") == 0) { - /* Turn off thread suppor mode */ + /* Turn off thread support mode */ nothreads = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i], "-safecstrings") == 0) { - safecstrings = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nosafecstrings") == 0) { - safecstrings = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-buildnone") == 0) { - buildnone = 1; - nobuildnone = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nobuildnone") == 0) { - buildnone = 0; - nobuildnone = 1; - Swig_mark_arg(i); } else if (strcmp(argv[i], "-dirvtable") == 0) { dirvtable = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nodirvtable") == 0) { - dirvtable = 0; + } else if (strcmp(argv[i], "-doxygen") == 0) { + doxygen = 1; + scan_doxygen_comments = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i], "-fastunpack") == 0) { - fastunpack = 1; + } else if (strcmp(argv[i], "-debug-doxygen-translator") == 0) { + doxygen_translator_flags |= DoxygenTranslator::debug_translator; + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-debug-doxygen-parser") == 0) { + doxygen_translator_flags |= DoxygenTranslator::debug_parser; Swig_mark_arg(i); } else if (strcmp(argv[i], "-nofastunpack") == 0) { fastunpack = 0; @@ -427,87 +363,26 @@ public: } else if (strcmp(argv[i], "-fastproxy") == 0) { fastproxy = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nofastproxy") == 0) { - fastproxy = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-fastquery") == 0) { - fastquery = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nofastquery") == 0) { - fastquery = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-fastinit") == 0) { - fastinit = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nofastinit") == 0) { - fastinit = 0; - Swig_mark_arg(i); } else if (strcmp(argv[i], "-olddefs") == 0) { olddefs = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i], "-noolddefs") == 0) { - olddefs = 0; - Swig_mark_arg(i); } else if (strcmp(argv[i], "-castmode") == 0) { castmode = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nocastmode") == 0) { - castmode = 0; - Swig_mark_arg(i); } else if (strcmp(argv[i], "-extranative") == 0) { extranative = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i], "-noextranative") == 0) { - extranative = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-modernargs") == 0) { - modernargs = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nomodernargs") == 0) { - modernargs = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-aliasobj0") == 0) { - aliasobj0 = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-noaliasobj0") == 0) { - aliasobj0 = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-proxydel") == 0) { - proxydel = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-noproxydel") == 0) { - proxydel = 0; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-modern") == 0) { - classic = 0; - modern = 1; - modernargs = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nomodern") == 0) { - modern = 0; - modernargs = 0; - Swig_mark_arg(i); } else if (strcmp(argv[i], "-noh") == 0) { no_header_file = 1; Swig_mark_arg(i); - } else if ((strcmp(argv[i], "-new_vwm") == 0) || (strcmp(argv[i], "-newvwm") == 0)) { - /* Turn on new value wrapper mpde */ + } else if (strcmp(argv[i], "-newvwm") == 0) { + /* Turn on new value wrapper mode */ + /* Undocumented option, did have -help text: New value wrapper mode, use only when everything else fails */ Swig_value_wrapper_mode(1); no_header_file = 1; Swig_mark_arg(i); } else if (strcmp(argv[i], "-O") == 0) { - classic = 0; - modern = 1; - safecstrings = 0; - buildnone = 0; - nobuildnone = 1; - classptr = 0; - proxydel = 0; - fastunpack = 1; fastproxy = 1; - fastinit = 1; - fastquery = 1; - modernargs = 1; Wrapper_fast_dispatch_mode_set(1); Wrapper_virtual_elimination_mode_set(1); Swig_mark_arg(i); @@ -526,19 +401,52 @@ public: } else if (strcmp(argv[i], "-relativeimport") == 0) { relativeimport = 1; Swig_mark_arg(i); + } else if (strcmp(argv[i], "-cppcast") == 0 || + strcmp(argv[i], "-fastinit") == 0 || + strcmp(argv[i], "-fastquery") == 0 || + strcmp(argv[i], "-fastunpack") == 0 || + strcmp(argv[i], "-modern") == 0 || + strcmp(argv[i], "-modernargs") == 0 || + strcmp(argv[i], "-noproxydel") == 0 || + strcmp(argv[i], "-safecstrings") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]); + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-aliasobj0") == 0 || + strcmp(argv[i], "-buildnone") == 0 || + strcmp(argv[i], "-classic") == 0 || + strcmp(argv[i], "-classptr") == 0 || + strcmp(argv[i], "-new_repr") == 0 || + strcmp(argv[i], "-new_vwm") == 0 || + strcmp(argv[i], "-newrepr") == 0 || + strcmp(argv[i], "-noaliasobj0") == 0 || + strcmp(argv[i], "-nobuildnone") == 0 || + strcmp(argv[i], "-nocastmode") == 0 || + strcmp(argv[i], "-nocppcast") == 0 || + strcmp(argv[i], "-nodirvtable") == 0 || + strcmp(argv[i], "-noextranative") == 0 || + strcmp(argv[i], "-nofastinit") == 0 || + strcmp(argv[i], "-nofastproxy") == 0 || + strcmp(argv[i], "-nofastquery") == 0 || + strcmp(argv[i], "-nomodern") == 0 || + strcmp(argv[i], "-nomodernargs") == 0 || + strcmp(argv[i], "-noolddefs") == 0 || + strcmp(argv[i], "-nooutputtuple") == 0 || + strcmp(argv[i], "-noproxyimport") == 0 || + strcmp(argv[i], "-nosafecstrings") == 0 || + strcmp(argv[i], "-old_repr") == 0 || + strcmp(argv[i], "-oldrepr") == 0 || + strcmp(argv[i], "-outputtuple") == 0 || + strcmp(argv[i], "-proxydel") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]); + Swig_mark_arg(i); + SWIG_exit(EXIT_FAILURE); } } } - if (py3) { - /* force disable features that not compatible with Python 3.x */ - classic = 0; - } - - if (cppcast) { - Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0); - } + if (doxygen) + doxygenTranslator = new PyDocConverter(doxygen_translator_flags); if (!global_name) global_name = NewString("cvar"); @@ -554,15 +462,16 @@ public: * ------------------------------------------------------------ */ virtual int top(Node *n) { - /* check if directors are enabled for this module. note: this + /* check if directors are enabled for this module. note: this * is a "master" switch, without which no director code will be * emitted. %feature("director") statements are also required * to enable directors for individual classes or methods. * - * use %module(directors="1") modulename at the start of the + * use %module(directors="1") modulename at the start of the * interface file to enable director generation. */ String *mod_docstring = NULL; + String *moduleimport = NULL; { Node *mod = Getattr(n, "module"); if (mod) { @@ -587,22 +496,27 @@ public: castmode = 1; } if (Getattr(options, "nocastmode")) { - castmode = 0; + Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "nocastmode"); + SWIG_exit(EXIT_FAILURE); } if (Getattr(options, "extranative")) { extranative = 1; } if (Getattr(options, "noextranative")) { - extranative = 0; + Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "noextranative"); + SWIG_exit(EXIT_FAILURE); } if (Getattr(options, "outputtuple")) { - outputtuple = 1; + Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "outputtuple"); + SWIG_exit(EXIT_FAILURE); } if (Getattr(options, "nooutputtuple")) { - outputtuple = 0; + Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "nooutputtuple"); + SWIG_exit(EXIT_FAILURE); } mod_docstring = Getattr(options, "docstring"); package = Getattr(options, "package"); + moduleimport = Getattr(options, "moduleimport"); } } } @@ -626,6 +540,8 @@ public: f_directors_h = NewString(""); f_directors = NewString(""); builtin_getset = NewHash(); + builtin_closures = NewHash(); + builtin_closures_code = NewString(""); class_members = NewHash(); builtin_methods = NewString(""); builtin_default_unref = NewString("delete $self;"); @@ -657,6 +573,7 @@ public: const_code = NewString(""); methods = NewString(""); + methods_proxydocs = NewString(""); Swig_banner(f_begin); @@ -672,26 +589,10 @@ public: Printf(f_runtime, "#define SWIG_PYTHON_THREADS\n"); } - if (safecstrings) { - Printf(f_runtime, "#define SWIG_PYTHON_SAFE_CSTRINGS\n"); - } - - if (buildnone) { - Printf(f_runtime, "#define SWIG_PYTHON_BUILD_NONE\n"); - } - - if (nobuildnone) { - Printf(f_runtime, "#define SWIG_PYTHON_NO_BUILD_NONE\n"); - } - if (!dirvtable) { Printf(f_runtime, "#define SWIG_PYTHON_DIRECTOR_NO_VTABLE\n"); } - if (outputtuple) { - Printf(f_runtime, "#define SWIG_PYTHON_OUTPUT_TUPLE\n"); - } - if (nortti) { Printf(f_runtime, "#ifndef SWIG_DIRECTOR_NORTTI\n"); Printf(f_runtime, "#define SWIG_DIRECTOR_NORTTI\n"); @@ -707,46 +608,16 @@ public: Printf(f_runtime, "#define SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS\n"); } - if (classic) { - Printf(f_runtime, "#define SWIG_PYTHON_CLASSIC\n"); - } - if (builtin) { Printf(f_runtime, "#define SWIGPYTHON_BUILTIN\n"); } Printf(f_runtime, "\n"); - Printf(f_header, "#if (PY_VERSION_HEX <= 0x02000000)\n"); - Printf(f_header, "# if !defined(SWIG_PYTHON_CLASSIC)\n"); - Printf(f_header, "# error \"This python version requires swig to be run with the '-classic' option\"\n"); - Printf(f_header, "# endif\n"); + Printf(f_header, "#ifdef SWIG_TypeQuery\n"); + Printf(f_header, "# undef SWIG_TypeQuery\n"); Printf(f_header, "#endif\n"); - - if (modern) { - Printf(f_header, "#if (PY_VERSION_HEX <= 0x02020000)\n"); - Printf(f_header, "# error \"This python version requires swig to be run with the '-nomodern' option\"\n"); - Printf(f_header, "#endif\n"); - } - - if (modernargs) { - Printf(f_header, "#if (PY_VERSION_HEX <= 0x02020000)\n"); - Printf(f_header, "# error \"This python version requires swig to be run with the '-nomodernargs' option\"\n"); - Printf(f_header, "#endif\n"); - } - - if (fastunpack) { - Printf(f_header, "#ifndef METH_O\n"); - Printf(f_header, "# error \"This python version requires swig to be run with the '-nofastunpack' option\"\n"); - Printf(f_header, "#endif\n"); - } - - if (fastquery) { - Printf(f_header, "#ifdef SWIG_TypeQuery\n"); - Printf(f_header, "# undef SWIG_TypeQuery\n"); - Printf(f_header, "#endif\n"); - Printf(f_header, "#define SWIG_TypeQuery SWIG_Python_TypeQuery\n"); - } + Printf(f_header, "#define SWIG_TypeQuery SWIG_Python_TypeQuery\n"); /* Set module name */ @@ -775,6 +646,7 @@ public: } /* If shadow classing is enabled, we're going to change the module name to "_module" */ + String *default_import_code = NewString(""); if (shadow) { String *filen = NewStringf("%s%s.py", SWIG_output_directory(), Char(module)); // If we don't have an interface then change the module name X to _X @@ -792,193 +664,101 @@ public: f_shadow = NewString(""); f_shadow_begin = NewString(""); f_shadow_imports = NewHash(); - f_shadow_builtin_imports = NewString(""); + f_shadow_after_begin = NewString(""); f_shadow_stubs = NewString(""); Swig_register_filebyname("shadow", f_shadow); Swig_register_filebyname("python", f_shadow); - if (mod_docstring) { - if (Len(mod_docstring)) { - const char *triple_double = "\"\"\""; - // follow PEP257 rules: https://www.python.org/dev/peps/pep-0257/ - // reported by pep257: https://github.com/GreenSteam/pep257 - bool multi_line_ds = Strchr(mod_docstring, '\n') != 0; - Printv(f_shadow, triple_double, multi_line_ds ? "\n":"", mod_docstring, multi_line_ds ? "\n":"", triple_double, "\n\n", NIL); - } - Delete(mod_docstring); - mod_docstring = NULL; - } - - Printv(f_shadow, "\nfrom sys import version_info as _swig_python_version_info\n", NULL); - - if (!builtin && fastproxy) { - Printv(f_shadow, "if _swig_python_version_info >= (3, 0, 0):\n", NULL); - Printf(f_shadow, tab4 "new_instancemethod = lambda func, inst, cls: %s.SWIG_PyInstanceMethod_New(func)\n", module); - Printv(f_shadow, "else:\n", NULL); - Printv(f_shadow, tab4, "from new import instancemethod as new_instancemethod\n", NULL); - } - - /* Import the C-extension module. This should be a relative import, - * since the shadow module may also have been imported by a relative - * import, and there is thus no guarantee that the C-extension is on - * sys.path. Relative imports must be explicitly specified from 2.6.0 - * onwards (implicit relative imports will raise a DeprecationWarning - * in 2.6, and fail in 2.7 onwards), but the relative import syntax - * isn't available in python 2.4 or earlier, so we have to write some - * code conditional on the python version. - * - * For python 2.7.0 and newer, first determine the shadow wrappers package - * based on the __name__ it was given by the importer that loaded it. - * Then construct a name for the module based on the package name and the - * module name (we know the module name). Use importlib to try and load - * it. If an attempt to load the module with importlib fails with an - * ImportError then fallback and try and load just the module name from - * the global namespace. - */ - Printv(f_shadow, "if _swig_python_version_info >= (2, 7, 0):\n", NULL); - Printv(f_shadow, tab4, "def swig_import_helper():\n", NULL); - Printv(f_shadow, tab8, "import importlib\n", NULL); - Printv(f_shadow, tab8, "pkg = __name__.rpartition('.')[0]\n", NULL); - Printf(f_shadow, tab8 "mname = '.'.join((pkg, '%s')).lstrip('.')\n", - module); - Printv(f_shadow, tab8, "try:\n", NULL); - Printv(f_shadow, tab8, tab4, "return importlib.import_module(mname)\n", - NULL); - Printv(f_shadow, tab8, "except ImportError:\n", NULL); - Printf(f_shadow, tab8 tab4 "return importlib.import_module('%s')\n", - module); - Printf(f_shadow, tab4 "%s = swig_import_helper()\n", module); - Printv(f_shadow, tab4, "del swig_import_helper\n", NULL); - Printv(f_shadow, "elif _swig_python_version_info >= (2, 6, 0):\n", NULL); - Printv(f_shadow, tab4, "def swig_import_helper():\n", NULL); - Printv(f_shadow, tab8, "from os.path import dirname\n", NULL); - Printv(f_shadow, tab8, "import imp\n", NULL); - Printv(f_shadow, tab8, "fp = None\n", NULL); - Printv(f_shadow, tab8, "try:\n", NULL); - Printf(f_shadow, tab4 tab8 "fp, pathname, description = imp.find_module('%s', [dirname(__file__)])\n", module); - Printf(f_shadow, tab8 "except ImportError:\n"); - /* At here, the module may already loaded, so simply import it. */ - Printf(f_shadow, tab4 tab8 "import %s\n", module); - Printf(f_shadow, tab4 tab8 "return %s\n", module); - Printv(f_shadow, tab8 "try:\n", NULL); - /* imp.load_module() handles fp being None. */ - Printf(f_shadow, tab4 tab8 "_mod = imp.load_module('%s', fp, pathname, description)\n", module); - Printv(f_shadow, tab8, "finally:\n", NULL); - Printv(f_shadow, tab4 tab8 "if fp is not None:\n", NULL); - Printv(f_shadow, tab8 tab8, "fp.close()\n", NULL); - Printv(f_shadow, tab8, "return _mod\n", NULL); - Printf(f_shadow, tab4 "%s = swig_import_helper()\n", module); - Printv(f_shadow, tab4, "del swig_import_helper\n", NULL); - Printv(f_shadow, "else:\n", NULL); - Printf(f_shadow, tab4 "import %s\n", module); - - if (builtin) { - /* - * Pull in all the attributes from the C module. - * - * An alternative approach to doing this if/else chain was - * proposed by Michael Thon. Someone braver than I may try it out. - * I fear some current swig user may depend on some side effect - * of from _foo import * - * - * for attr in _foo.__all__: - * globals()[attr] = getattr(_foo, attr) - * - */ - Printf(f_shadow, "# pull in all the attributes from %s\n", module); - Printv(f_shadow, "if __name__.rpartition('.')[0] != '':\n", NULL); - Printv(f_shadow, tab4, "if _swig_python_version_info >= (2, 7, 0):\n", NULL); - Printv(f_shadow, tab8, "try:\n", NULL); - Printf(f_shadow, tab8 tab4 "from .%s import *\n", module); - Printv(f_shadow, tab8 "except ImportError:\n", NULL); - Printf(f_shadow, tab8 tab4 "from %s import *\n", module); - Printv(f_shadow, tab4, "else:\n", NULL); - Printf(f_shadow, tab8 "from %s import *\n", module); - Printv(f_shadow, "else:\n", NULL); - Printf(f_shadow, tab4 "from %s import *\n", module); - } - - /* Delete the _swig_python_version_info symbol since we don't use it elsewhere in the - * module. */ - Printv(f_shadow, "del _swig_python_version_info\n", NULL); - - if (modern || !classic) { - Printv(f_shadow, "try:\n", tab4, "_swig_property = property\n", "except NameError:\n", tab4, "pass # Python < 2.2 doesn't have 'property'.\n\n", NULL); + if (!builtin) { + /* Import the low-level C/C++ module. This should be a relative import, + * since the shadow module may also have been imported by a relative + * import, and there is thus no guarantee that the low-level C/C++ module is on + * sys.path. Relative imports must be explicitly specified from 2.6.0 + * onwards (implicit relative imports raised a DeprecationWarning in 2.6, + * and fail in 2.7 onwards). + * + * First check for __package__ which is available from 2.6 onwards, see PEP366. + * Next try determine the shadow wrapper's package based on the __name__ it + * was given by the importer that loaded it. + * If the module is in a package, load the low-level C/C++ module from the + * same package, otherwise load it as a global module. + */ + Printv(default_import_code, "# Import the low-level C/C++ module\n", NULL); + Printv(default_import_code, "if __package__ or \".\" in __name__:\n", NULL); + Printv(default_import_code, tab4, "from . import ", module, "\n", NULL); + Printv(default_import_code, "else:\n", NULL); + Printv(default_import_code, tab4, "import ", module, "\n", NULL); + } else { + Printv(default_import_code, "# Pull in all the attributes from the low-level C/C++ module\n", NULL); + Printv(default_import_code, "if __package__ or \".\" in __name__:\n", NULL); + Printv(default_import_code, tab4, "from .", module, " import *\n", NULL); + Printv(default_import_code, "else:\n", NULL); + Printv(default_import_code, tab4, "from ", module, " import *\n", NULL); } /* Need builtins to qualify names like Exception that might also be defined in this module (try both Python 3 and Python 2 names) */ Printv(f_shadow, "try:\n", tab4, "import builtins as __builtin__\n", "except ImportError:\n", tab4, "import __builtin__\n", NULL); - /* if (!modern) */ - /* always needed, a class can be forced to be no-modern, such as an exception */ - { - // Python-2.2 object hack - Printv(f_shadow, - "\n", "def _swig_setattr_nondynamic(self, class_type, name, value, static=1):\n", - tab4, "if (name == \"thisown\"):\n", tab8, "return self.this.own(value)\n", - tab4, "if (name == \"this\"):\n", tab8, "if type(value).__name__ == 'SwigPyObject':\n", tab4, tab8, "self.__dict__[name] = value\n", -#ifdef USE_THISOWN - tab4, tab8, "if hasattr(value,\"thisown\"):\n", tab8, tab8, "self.__dict__[\"thisown\"] = value.thisown\n", tab4, tab8, "del value.thisown\n", -#endif - tab4, tab8, "return\n", tab4, "method = class_type.__swig_setmethods__.get(name, None)\n", tab4, "if method:\n", tab4, tab4, "return method(self, value)\n", -#ifdef USE_THISOWN - tab4, "if (not static) or (name == \"thisown\"):\n", -#else - tab4, "if (not static):\n", -#endif - NIL); - if (!classic) { - if (!modern) - Printv(f_shadow, tab4, tab4, "if _newclass:\n", tab4, NIL); - Printv(f_shadow, tab4, tab4, "object.__setattr__(self, name, value)\n", NIL); - if (!modern) - Printv(f_shadow, tab4, tab4, "else:\n", tab4, NIL); - } - if (classic || !modern) - Printv(f_shadow, tab4, tab4, "self.__dict__[name] = value\n", NIL); - Printv(f_shadow, - tab4, "else:\n", - tab4, tab4, "raise AttributeError(\"You cannot add attributes to %s\" % self)\n\n", - "\n", "def _swig_setattr(self, class_type, name, value):\n", tab4, "return _swig_setattr_nondynamic(self, class_type, name, value, 0)\n\n", NIL); - - Printv(f_shadow, - "\n", "def _swig_getattr(self, class_type, name):\n", - tab4, "if (name == \"thisown\"):\n", tab8, "return self.this.own()\n", - tab4, "method = class_type.__swig_getmethods__.get(name, None)\n", - tab4, "if method:\n", tab8, "return method(self)\n", - tab4, "raise AttributeError(\"'%s' object has no attribute '%s'\" % (class_type.__name__, name))\n\n", NIL); - - Printv(f_shadow, - "\n", "def _swig_repr(self):\n", - tab4, "try:\n", tab8, "strthis = \"proxy of \" + self.this.__repr__()\n", - tab4, "except __builtin__.Exception:\n", tab8, "strthis = \"\"\n", tab4, "return \"<%s.%s; %s >\" % (self.__class__.__module__, self.__class__.__name__, strthis,)\n\n", NIL); - - if (!classic && !modern) { - Printv(f_shadow, - "try:\n", - tab4, "_object = object\n", tab4, "_newclass = 1\n", - "except __builtin__.Exception:\n", - tab4, "class _object:\n", tab8, "pass\n", tab4, "_newclass = 0\n\n", NIL); - } + if (!builtin && fastproxy) { + Printf(f_shadow, "\n"); + Printf(f_shadow, "_swig_new_instance_method = %s.SWIG_PyInstanceMethod_New\n", module); + Printf(f_shadow, "_swig_new_static_method = %s.SWIG_PyStaticMethod_New\n", module); } - if (modern) { - Printv(f_shadow, "\n", "def _swig_setattr_nondynamic_method(set):\n", tab4, "def set_attr(self, name, value):\n", + + Printv(f_shadow, "\n", + "def _swig_repr(self):\n", + tab4, "try:\n", + tab4, tab4, "strthis = \"proxy of \" + self.this.__repr__()\n", + tab4, "except __builtin__.Exception:\n", + tab4, tab4, "strthis = \"\"\n", + tab4, "return \"<%s.%s; %s >\" % (self.__class__.__module__, self.__class__.__name__, strthis,)\n\n", NIL); + + Printv(f_shadow, "\n", + "def _swig_setattr_nondynamic_instance_variable(set):\n", + tab4, "def set_instance_attr(self, name, value):\n", #ifdef USE_THISOWN - tab4, tab4, "if hasattr(self, name) or (name in (\"this\", \"thisown\")):\n", + tab4, tab4, "if name in (\"this\", \"thisown\"):\n", + tab4, tab4, tab4, "set(self, name, value)\n", #else - tab4, tab4, "if (name == \"thisown\"):\n", tab8, tab4, "return self.this.own(value)\n", tab4, tab4, "if hasattr(self, name) or (name == \"this\"):\n", + tab4, tab4, "if name == \"thisown\":\n", + tab4, tab4, tab4, "self.this.own(value)\n", + tab4, tab4, "elif name == \"this\":\n", + tab4, tab4, tab4, "set(self, name, value)\n", #endif - tab4, tab4, tab4, "set(self, name, value)\n", - tab4, tab4, "else:\n", - tab4, tab4, tab4, "raise AttributeError(\"You cannot add attributes to %s\" % self)\n", tab4, "return set_attr\n\n\n", NIL); - } + tab4, tab4, "elif hasattr(self, name) and isinstance(getattr(type(self), name), property):\n", + tab4, tab4, tab4, "set(self, name, value)\n", + tab4, tab4, "else:\n", + tab4, tab4, tab4, "raise AttributeError(\"You cannot add instance attributes to %s\" % self)\n", + tab4, "return set_instance_attr\n\n", NIL); + + Printv(f_shadow, "\n", + "def _swig_setattr_nondynamic_class_variable(set):\n", + tab4, "def set_class_attr(cls, name, value):\n", + tab4, tab4, "if hasattr(cls, name) and not isinstance(getattr(cls, name), property):\n", + tab4, tab4, tab4, "set(cls, name, value)\n", + tab4, tab4, "else:\n", + tab4, tab4, tab4, "raise AttributeError(\"You cannot add class attributes to %s\" % cls)\n", + tab4, "return set_class_attr\n\n", NIL); + + Printv(f_shadow, "\n", + "def _swig_add_metaclass(metaclass):\n", + tab4, "\"\"\"Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass\"\"\"\n", + tab4, "def wrapper(cls):\n", + tab4, tab4, "return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())\n", + tab4, "return wrapper\n\n", NIL); + + Printv(f_shadow, "\n", + "class _SwigNonDynamicMeta(type):\n", + tab4, "\"\"\"Meta class to enforce nondynamic attributes (no new attributes) for a class\"\"\"\n", + tab4, "__setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)\n", + "\n", NIL); + + Printv(f_shadow, "\n", NIL); if (directorsEnabled()) { - // Try loading weakref.proxy, which is only available in Python 2.1 and higher - Printv(f_shadow, - "try:\n", tab4, "import weakref\n", tab4, "weakref_proxy = weakref.proxy\n", "except __builtin__.Exception:\n", tab4, "weakref_proxy = lambda x: x\n", "\n\n", NIL); + Printv(f_shadow, "import weakref\n\n", NIL); } } // Include some information in the code @@ -997,9 +777,11 @@ public: Printf(f_wrappers, "#endif\n"); Append(const_code, "static swig_const_info swig_const_table[] = {\n"); Append(methods, "static PyMethodDef SwigMethods[] = {\n"); + Append(methods_proxydocs, "static PyMethodDef SwigMethods_proxydocs[] = {\n"); /* the method exported for replacement of new.instancemethod in Python 3 */ add_pyinstancemethod_new(); + add_pystaticmethod_new(); if (builtin) { SwigType *s = NewString("SwigPyObject"); @@ -1021,6 +803,9 @@ public: Append(methods, "\t { NULL, NULL, 0, NULL }\n"); Append(methods, "};\n"); Printf(f_wrappers, "%s\n", methods); + Append(methods_proxydocs, "\t { NULL, NULL, 0, NULL }\n"); + Append(methods_proxydocs, "};\n"); + Printf(f_wrappers, "%s\n", methods_proxydocs); if (builtin) { Dump(f_builtins, f_wrappers); @@ -1045,12 +830,37 @@ public: if (shadow) { Swig_banner_target_lang(f_shadow_py, "#"); - if (!modern && !classic) { - Printv(f_shadow, "# This file is compatible with both classic and new-style classes.\n", NIL); + + if (mod_docstring) { + if (Len(mod_docstring)) { + const char *triple_double = "\"\"\""; + // follow PEP257 rules: https://www.python.org/dev/peps/pep-0257/ + // reported by pep257: https://github.com/GreenSteam/pep257 + bool multi_line_ds = Strchr(mod_docstring, '\n') != 0; + Printv(f_shadow_py, "\n", triple_double, multi_line_ds ? "\n":"", mod_docstring, multi_line_ds ? "\n":"", triple_double, "\n", NIL); + } + Delete(mod_docstring); + mod_docstring = NULL; } - Printv(f_shadow_py, "\n", f_shadow_begin, "\n", NIL); - Printv(f_shadow_py, "\n", f_shadow_builtin_imports, "\n", NIL); - Printv(f_shadow_py, f_shadow, "\n", NIL); + + if (Len(f_shadow_begin) > 0) + Printv(f_shadow_py, "\n", f_shadow_begin, "\n", NIL); + + Printv(f_shadow_py, "\nfrom sys import version_info as _swig_python_version_info\n", NULL); + Printv(f_shadow_py, "if _swig_python_version_info < (2, 7, 0):\n", NULL); + Printv(f_shadow_py, tab4, "raise RuntimeError(\"Python 2.7 or later required\")\n\n", NULL); + + if (Len(f_shadow_after_begin) > 0) + Printv(f_shadow_py, f_shadow_after_begin, "\n", NIL); + + if (moduleimport) { + Replaceall(moduleimport, "$module", module); + Printv(f_shadow_py, moduleimport, "\n", NIL); + } else { + Printv(f_shadow_py, default_import_code, NIL); + } + + Printv(f_shadow_py, "\n", f_shadow, "\n", NIL); Printv(f_shadow_py, f_shadow_stubs, "\n", NIL); Delete(f_shadow_py); } @@ -1073,6 +883,11 @@ public: Printf(f_begin, "static PyTypeObject *builtin_bases[%d];\n\n", max_bases + 2); Wrapper_pretty_print(f_init, f_begin); + Delete(default_import_code); + Delete(f_shadow_after_begin); + Delete(f_shadow_imports); + Delete(f_shadow_begin); + Delete(f_shadow); Delete(f_header); Delete(f_wrappers); Delete(f_builtins); @@ -1092,11 +907,35 @@ public: * ------------------------------------------------------------ */ int add_pyinstancemethod_new() { String *name = NewString("SWIG_PyInstanceMethod_New"); - Printf(methods, "\t { (char *)\"%s\", (PyCFunction)%s, METH_O, NULL},\n", name, name); + String *line = NewString(""); + Printf(line, "\t { \"%s\", %s, METH_O, NULL},\n", name, name); + Append(methods, line); + if (fastproxy) { + Append(methods_proxydocs, line); + } + Delete(line); Delete(name); return 0; } + /* ------------------------------------------------------------ + * Emit the wrapper for PyStaticMethod_New to MethodDef array. + * This wrapper is used to ensure the correct documentation is + * generated for static methods when using -fastproxy + * ------------------------------------------------------------ */ + int add_pystaticmethod_new() { + if (fastproxy) { + String *name = NewString("SWIG_PyStaticMethod_New"); + String *line = NewString(""); + Printf(line, "\t { \"%s\", %s, METH_O, NULL},\n", name, name); + Append(methods, line); + Append(methods_proxydocs, line); + Delete(line); + Delete(name); + } + return 0; + } + /* ------------------------------------------------------------ * subpkg_tail() * @@ -1252,14 +1091,9 @@ public: Printf(out, "import %s%s%s%s\n", apkg, *Char(apkg) ? "." : "", pfx, mod); Delete(apkg); } else { - Printf(out, "from sys import version_info as _swig_python_version_info\n"); - Printf(out, "if _swig_python_version_info >= (2, 7, 0):\n"); if (py3_rlen1) - Printf(out, tab4 "from . import %.*s\n", py3_rlen1, rpkg); - Printf(out, tab4 "from .%s import %s%s\n", rpkg, pfx, mod); - Printf(out, "else:\n"); - Printf(out, tab4 "import %s%s%s%s\n", rpkg, *Char(rpkg) ? "." : "", pfx, mod); - Printf(out, "del _swig_python_version_info\n"); + Printf(out, "from . import %.*s\n", py3_rlen1, rpkg); + Printf(out, "from .%s import %s%s\n", rpkg, pfx, mod); Delete(rpkg); } return out; @@ -1376,18 +1210,18 @@ public: Node *options = Getattr(mod, "options"); String *pkg = options ? Getattr(options, "package") : 0; - if (shadowimport) { - if (!options || (!Getattr(options, "noshadow") && !Getattr(options, "noproxy"))) { - String *_import = import_directive_string(package, pkg, modname, "_"); - if (!GetFlagAttr(f_shadow_imports, _import)) { - String *import = import_directive_string(package, pkg, modname); - Printf(builtin ? f_shadow_builtin_imports : f_shadow, "%s", import); - Delete(import); - SetFlag(f_shadow_imports, _import); - } - Delete(_import); + + if (!options || (!Getattr(options, "noshadow") && !Getattr(options, "noproxy"))) { + String *_import = import_directive_string(package, pkg, modname, "_"); + if (!GetFlagAttr(f_shadow_imports, _import)) { + String *import = import_directive_string(package, pkg, modname); + Printf(builtin ? f_shadow_after_begin : f_shadow, "%s", import); + Delete(import); + SetFlag(f_shadow_imports, _import); } + Delete(_import); } + } } return Language::importDirective(n); @@ -1631,7 +1465,94 @@ public: bool have_docstring(Node *n) { String *str = Getattr(n, "feature:docstring"); - return (str && Len(str) > 0) || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")); + return ((str && Len(str) > 0) + || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")) + || (doxygen && doxygenTranslator->hasDocumentation(n)) + ); + } + + /* ------------------------------------------------------------ + * build_combined_docstring() + * + * Build the full docstring which may be a combination of the + * explicit docstring and autodoc string or, if none of them + * is specified, obtained by translating Doxygen comment to + * Python. + * + * Return new string to be deleted by caller (never NIL but + * may be empty if there is no docstring). + * ------------------------------------------------------------ */ + + String *build_combined_docstring(Node *n, autodoc_t ad_type, const String *indent = "", bool low_level = false) { + String *docstr = Getattr(n, "feature:docstring"); + if (docstr && Len(docstr)) { + docstr = Copy(docstr); + char *t = Char(docstr); + if (*t == '{') { + Delitem(docstr, 0); + Delitem(docstr, DOH_END); + } + } + + if (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")) { + String *autodoc = make_autodoc(n, ad_type, low_level); + if (autodoc && Len(autodoc) > 0) { + if (docstr && Len(docstr)) { + Append(autodoc, "\n"); + Append(autodoc, docstr); + } + + String *tmp = autodoc; + autodoc = docstr; + docstr = tmp; + } + + Delete(autodoc); + } + + if (!docstr || !Len(docstr)) { + if (doxygen) { + docstr = Getattr(n, "python:docstring"); + if (!docstr && doxygenTranslator->hasDocumentation(n)) { + docstr = doxygenTranslator->getDocumentation(n, 0); + + // Avoid rebuilding it again the next time: notice that we can't do + // this for the combined doc string as autodoc part of it depends on + // the sym:name of the node and it is changed while handling it, so + // the cached results become incorrect. But Doxygen docstring only + // depends on the comment which is not going to change, so we can + // safely cache it. + Setattr(n, "python:docstring", Copy(docstr)); + } else { + // Must copy here since if the docstring is multi-line, the String* + // here will get Deleted below, which is bad if it is a pointer to + // the cached object! + docstr = Copy(docstr); + } + } + } + + if (!docstr) + docstr = NewString(""); + + // If there is more than one line then make docstrings like this: + // + // """ + // This is line1 + // And here is line2 followed by the rest of them + // """ + // + // otherwise, put it all on a single line + if (Strchr(docstr, '\n')) { + String *tmp = NewString(""); + Append(tmp, "\n"); + Append(tmp, indent_docstring(docstr, indent)); + Append(tmp, indent); + Delete(docstr); + docstr = tmp; + } + + return docstr; } /* ------------------------------------------------------------ @@ -1642,110 +1563,59 @@ public: * set then it will build a combined docstring. * ------------------------------------------------------------ */ - String *docstring(Node *n, autodoc_t ad_type, const String *indent, bool use_triple = true) { - String *str = Getattr(n, "feature:docstring"); - bool have_ds = (str && Len(str) > 0); - bool have_auto = (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")); - const char *triple_double = use_triple ? "\"\"\"" : ""; - String *autodoc = NULL; - String *doc = NULL; + String *docstring(Node *n, autodoc_t ad_type, const String *indent, bool low_level = false) { + String *docstr = build_combined_docstring(n, ad_type, indent, low_level); + if (!Len(docstr)) + return docstr; - if (have_ds) { - char *t = Char(str); - if (*t == '{') { - Delitem(str, 0); - Delitem(str, DOH_END); - } - } + // Notice that all comments are created as raw strings (prefix "r"), + // because '\' is used often in comments, but may break Python module from + // loading. For example, in doxy comment one may write path in quotes: + // + // This is path to file "C:\x\file.txt" + // + // Python will not load the module with such comment because of illegal + // escape '\x'. '\' may additionally appear in verbatim or htmlonly sections + // of doxygen doc, Latex expressions, ... + String *doc = NewString(""); + Append(doc, "r\"\"\""); + Append(doc, docstr); + Append(doc, "\"\"\""); + Delete(docstr); - if (have_auto) { - autodoc = make_autodoc(n, ad_type); - have_auto = (autodoc && Len(autodoc) > 0); - } - // If there is more than one line then make docstrings like this: - // - // """ - // This is line1 - // And here is line2 followed by the rest of them - // """ - // - // otherwise, put it all on a single line - // - if (have_auto && have_ds) { // Both autodoc and docstring are present - doc = NewString(""); - Printv(doc, triple_double, "\n", - indent_docstring(autodoc, indent), "\n", - indent_docstring(str, indent), indent, triple_double, NIL); - } else if (!have_auto && have_ds) { // only docstring - if (Strchr(str, '\n') == 0) { - doc = NewStringf("%s%s%s", triple_double, str, triple_double); - } else { - doc = NewString(""); - Printv(doc, triple_double, "\n", indent_docstring(str, indent), indent, triple_double, NIL); - } - } else if (have_auto && !have_ds) { // only autodoc - if (Strchr(autodoc, '\n') == 0) { - doc = NewStringf("%s%s%s", triple_double, autodoc, triple_double); - } else { - doc = NewString(""); - Printv(doc, triple_double, "\n", indent_docstring(autodoc, indent), indent, triple_double, NIL); - } - } else - doc = NewString(""); - - // Save the generated strings in the parse tree in case they are used later - // by post processing tools - Setattr(n, "python:docstring", doc); - Setattr(n, "python:autodoc", autodoc); return doc; - } + } /* ------------------------------------------------------------ * cdocstring() * * Get the docstring text as it would appear in C-language - * source code. + * source code (but without quotes around it). * ------------------------------------------------------------ */ - String *cdocstring(Node *n, autodoc_t ad_type) - { - String *ds = docstring(n, ad_type, "", false); + String *cdocstring(Node *n, autodoc_t ad_type, bool low_level = false) { + String *ds = build_combined_docstring(n, ad_type, "", low_level); Replaceall(ds, "\\", "\\\\"); Replaceall(ds, "\"", "\\\""); Replaceall(ds, "\n", "\\n\"\n\t\t\""); return ds; } - virtual String *makeParameterName(Node *n, Parm *p, int arg_num, bool = false) const { - // For the keyword arguments, we want to preserve the names as much as possible, - // so we only minimally rename them in Swig_name_make(), e.g. replacing "keyword" - // with "_keyword" if they have any name at all. - if (check_kwargs(n)) { - String *name = Getattr(p, "name"); - if (name) - return Swig_name_make(p, 0, name, 0, 0); - } - - // For the other cases use the general function which replaces arguments whose - // names clash with keywords with (less useful) "argN". - return Language::makeParameterName(n, p, arg_num); - } - /* ----------------------------------------------------------------------------- * addMissingParameterNames() * * For functions that have not had nameless parameters set in the Language class. * - * Inputs: + * Inputs: * plist - entire parameter list - * arg_offset - argument number for first parameter + * arg_num - the number to start from when naming arguments * Side effects: * The "lname" attribute in each parameter in plist will be contain a parameter name * ----------------------------------------------------------------------------- */ - void addMissingParameterNames(Node *n, ParmList *plist, int arg_offset) { + void addMissingParameterNames(Node *n, ParmList *plist, int arg_num) { Parm *p = plist; - int i = arg_offset; + int i = arg_num; while (p) { if (!Getattr(p, "lname")) { String *name = makeParameterName(n, p, i); @@ -1762,10 +1632,11 @@ public: * * Generate the documentation for the function parameters * Parameters: + * arg_num: The number to start assigning unnamed arguments from * func_annotation: Function annotation support * ------------------------------------------------------------ */ - String *make_autodocParmList(Node *n, bool showTypes, bool calling = false, bool func_annotation = false) { + String *make_autodocParmList(Node *n, bool showTypes, int arg_num = 1, bool calling = false, bool func_annotation = false) { String *doc = NewString(""); String *pdocs = 0; @@ -1773,15 +1644,6 @@ public: Parm *p; Parm *pnext; - - // Normally we start counting auto-generated argument names from 1, but we should do it from 2 - // if the first argument is "self", i.e. if we're handling a non-static member function. - int arg_num = 1; - if (is_wrapping_class()) { - if (Cmp(Getattr(n, "storage"), "static") != 0) - arg_num++; - } - if (calling) func_annotation = false; @@ -1794,8 +1656,7 @@ public: return doc; } - for (p = plist; p; p = pnext, arg_num++) { - + for (p = plist; p; p = pnext) { String *tm = Getattr(p, "tmap:in"); if (tm) { pnext = Getattr(p, "tmap:in:next"); @@ -1816,12 +1677,21 @@ public: value = Getattr(p, "tmap:doc:value"); } + // Skip the "self" argument - it is added to the parameter list automatically + // and shouldn't be included in the Parameters block + if (Getattr(p, "self")) { + continue; + } + // Note: the generated name should be consistent with that in kwnames[] String *made_name = 0; if (!name) { name = made_name = makeParameterName(n, p, arg_num); } + // Increment the argument number once we are sure this is a real argument to count + arg_num++; + type = type ? type : Getattr(p, "type"); value = value ? value : Getattr(p, "value"); @@ -1850,13 +1720,24 @@ public: } // Write the function annotation if (func_annotation) - Printf(doc, ": '%s'", type_str); + Printf(doc, ": \"%s\"", type_str); // Write default value if (value && !calling) { String *new_value = convertValue(value, Getattr(p, "type")); + if (new_value) { + value = new_value; + } else { + // Even if the value is not representable in the target language, still use it in the documentation, for compatibility with the previous SWIG versions + // and because it can still be useful to see the C++ expression there. + Node *lookup = Swig_symbol_clookup(value, 0); + if (lookup) + value = Getattr(lookup, "sym:name"); + } + Printf(doc, "=%s", value); + if (new_value) - Printf(doc, "=%s", new_value); + Delete(new_value); } Delete(type_str); Delete(made_name); @@ -1878,8 +1759,9 @@ public: * and use it directly. * ------------------------------------------------------------ */ - String *make_autodoc(Node *n, autodoc_t ad_type) { + String *make_autodoc(Node *n, autodoc_t ad_type, bool low_level = false) { int extended = 0; + bool first_func = true; // If the function is overloaded then this function is called // for the last one. Rewind to the first so the docstrings are // in order. @@ -1916,10 +1798,24 @@ public: } if (!skipAuto) { - String *symname = Getattr(n, "sym:name"); + /* Check if a documentation name was given for either the low-level C API or high-level Python shadow API */ + String *symname = Getattr(n, low_level ? "doc:low:name" : "doc:high:name"); + if (!symname) { + symname = Getattr(n, "sym:name"); + } + SwigType *type = Getattr(n, "type"); String *type_str = NULL; + // If the function has default arguments, then that documentation covers this version too + if (Getattr(n, "defaultargs") != NULL) { + n = Getattr(n, "sym:nextSibling"); + continue; + } + + if (!first_func) + Append(doc, "\n"); + if (type) { if (Strcmp(type, "void") == 0) { type_str = NULL; @@ -1929,6 +1825,21 @@ public: } } + /* Treat the low-level C API functions for getting/setting variables as methods for documentation purposes */ + String *kind = Getattr(n, "kind"); + if (kind && Strcmp(kind, "variable") == 0) { + if (ad_type == AUTODOC_FUNC) { + ad_type = AUTODOC_METHOD; + } + } + /* Treat destructors as methods for documentation purposes */ + String *nodeType = Getattr(n, "nodeType"); + if (nodeType && Strcmp(nodeType, "destructor") == 0) { + if (ad_type == AUTODOC_FUNC) { + ad_type = AUTODOC_METHOD; + } + } + switch (ad_type) { case AUTODOC_CLASS: { @@ -1942,9 +1853,9 @@ public: Delete(rname); } else { if (CPlusPlus) { - Printf(doc, "Proxy of C++ %s class.", real_classname); + Printf(doc, "Proxy of C++ %s class.", SwigType_namestr(real_classname)); } else { - Printf(doc, "Proxy of C %s struct.", real_classname); + Printf(doc, "Proxy of C %s struct.", SwigType_namestr(real_classname)); } } } @@ -1952,10 +1863,10 @@ public: break; case AUTODOC_CTOR: if (Strcmp(class_name, symname) == 0) { - String *paramList = make_autodocParmList(n, showTypes); + String *paramList = make_autodocParmList(n, showTypes, 2); Printf(doc, "__init__("); if (showTypes) - Printf(doc, "%s ", getClassName()); + Printf(doc, "%s ", class_name); if (Len(paramList)) Printf(doc, "self, %s) -> %s", paramList, class_name); else @@ -1966,7 +1877,7 @@ public: case AUTODOC_DTOR: if (showTypes) - Printf(doc, "__del__(%s self)", getClassName()); + Printf(doc, "__del__(%s self)", class_name); else Printf(doc, "__del__(self)"); break; @@ -1984,35 +1895,133 @@ public: break; case AUTODOC_METHOD: - String *paramList = make_autodocParmList(n, showTypes); - Printf(doc, "%s(", symname); - if (showTypes) - Printf(doc, "%s ", class_name); - if (Len(paramList)) - Printf(doc, "self, %s)", paramList); - else - Printf(doc, "self)"); - if (type_str) - Printf(doc, " -> %s", type_str); + { + String *paramList = make_autodocParmList(n, showTypes, 2); + Printf(doc, "%s(", symname); + if (showTypes) + Printf(doc, "%s ", class_name); + if (Len(paramList)) + Printf(doc, "self, %s)", paramList); + else + Printf(doc, "self)"); + if (type_str) + Printf(doc, " -> %s", type_str); + } + break; + + case AUTODOC_CONST: + // There is no autodoc support for constants currently, this enum + // element only exists to allow calling docstring() with it. + return NULL; + case AUTODOC_VAR: + // Variables can also be documented (e.g. through the property() function in python) + Printf(doc, "%s", symname); + if (showTypes) { + String *type = Getattr(n, "tmap:doc:type"); + if (!type) + type = Getattr(n, "membervariableHandler:type"); + if (!type) + type = Getattr(n, "type"); + Printf(doc, " : %s", type); + } break; } Delete(type_str); - } - if (extended) { - String *pdocs = Getattr(n, "feature:pdocs"); - if (pdocs) { - Printv(doc, "\n", pdocs, NULL); + + // Special case: wrapper functions to get a variable should have no parameters. + // Because the node is re-used for the setter and getter, the feature:pdocs field will + // exist for the getter function, so explicitly avoid printing parameters in this case. + bool variable_getter = kind && Strcmp(kind, "variable") == 0 && Getattr(n, "memberget"); + if (extended && ad_type != AUTODOC_VAR && !variable_getter) { + String *pdocs = Getattr(n, "feature:pdocs"); + if (pdocs) { + Printv(doc, "\n", pdocs, NULL); + } } } // if it's overloaded then get the next decl and loop around again n = Getattr(n, "sym:nextSibling"); if (n) - Append(doc, "\n"); + first_func = false; } return doc; } + /* ------------------------------------------------------------ + * convertIntegerValue() + * + * Check if string v is an integer and can be represented in + * Python. If so, return an appropriate Python representation, + * otherwise (or if we are unsure), return NIL. + * ------------------------------------------------------------ */ + String *convertIntegerValue(String *v, SwigType *resolved_type) { + const char *const s = Char(v); + char *end; + String *result = NIL; + + // Check if this is an integer number in any base. + errno = 0; + long value = strtol(s, &end, 0); + if (errno == ERANGE || end == s) + return NIL; + + if (*end != '\0') { + // If there is a suffix after the number, we can safely ignore "l" + // and (provided the number is unsigned) "u", and also combinations of + // these, but not anything else. + for (char *p = end; *p != '\0'; ++p) { + switch (*p) { + case 'l': + case 'L': + break; + case 'u': + case 'U': + if (value < 0) + return NIL; + break; + default: + return NIL; + } + } + } + // So now we are certain that we are indeed dealing with an integer + // that has a representation as long given by value. + + // Restrict to guaranteed supported range in Python, see maxint docs: https://docs.python.org/2/library/sys.html#sys.maxint + // Don't do this pointless check when long is 32 bits or smaller as strtol will have already failed with ERANGE +#if LONG_MAX > PYTHON_INT_MAX || LONG_MIN < PYTHON_INT_MIN + if (value > PYTHON_INT_MAX || value < PYTHON_INT_MIN) { + return NIL; + } +#endif + + if (Cmp(resolved_type, "bool") == 0) + // Allow integers as the default value for a bool parameter. + return NewString(value ? "True" : "False"); + + if (value == 0) + return NewString(SwigType_ispointer(resolved_type) ? "None" : "0"); + + // v may still be octal or hexadecimal: + const char *p = s; + if (*p == '+' || *p == '-') + ++p; + if (*p == '0' && *(p+1) != 'x' && *(p+1) != 'X') { + // This must have been an octal number. This is the only case we + // cannot use in Python directly, since Python 2 and 3 use non- + // compatible representations. + result = NewString(*s == '-' ? "int(\"-" : "int(\""); + String *octal_string = NewStringWithSize(p, (int) (end - p)); + Append(result, octal_string); + Append(result, "\", 8)"); + Delete(octal_string); + return result; + } + result = *end == '\0' ? Copy(v) : NewStringWithSize(s, (int) (end - s)); + return result; + } + /* ------------------------------------------------------------ * convertDoubleValue() * @@ -2023,6 +2032,7 @@ public: const char *const s = Char(v); char *end; + errno = 0; double value = strtod(s, &end); (void) value; if (errno != ERANGE && end != s) { @@ -2051,7 +2061,7 @@ public: // Avoid unnecessary string allocation in the common case when we don't // need to remove any suffix. - return *end == '\0' ? v : NewStringWithSize(s, (int)(end - s)); + return *end == '\0' ? Copy(v) : NewStringWithSize(s, (int)(end - s)); } return NIL; @@ -2061,109 +2071,24 @@ public: * convertValue() * * Check if string v can be a Python value literal or a - * constant. Return NIL if it isn't. + * constant. Return an equivalent Python representation, + * or NIL if it isn't, or we are unsure. * ------------------------------------------------------------ */ String *convertValue(String *v, SwigType *type) { const char *const s = Char(v); - char *end; String *result = NIL; - bool fail = false; - SwigType *resolved_type = 0; + SwigType *resolved_type = SwigType_typedef_resolve_all(type); - // Check if this is a number in any base. - long value = strtol(s, &end, 0); - (void) value; - if (end != s) { - if (errno == ERANGE) { - // There was an overflow, we could try representing the value as Python - // long integer literal, but for now don't bother with it. - fail = true; - } else { - if (*end != '\0') { - // If there is a suffix after the number, we can safely ignore any - // combination of "l" and "u", but not anything else (again, stuff like - // "LL" could be handled, but we don't bother to do it currently). - bool seen_long = false; - for (char * p = end; *p != '\0'; ++p) { - switch (*p) { - case 'l': - case 'L': - // Bail out on "LL". - if (seen_long) { - fail = true; - break; - } - seen_long = true; - break; - - case 'u': - case 'U': - break; - - default: - // Except that our suffix could actually be the fractional part of - // a floating point number, so we still have to check for this. - result = convertDoubleValue(v); - } - } - } - - if (!fail) { - // Allow integers as the default value for a bool parameter. - resolved_type = SwigType_typedef_resolve_all(type); - if (Cmp(resolved_type, "bool") == 0) { - result = NewString(value ? "True" : "False"); - } else { - // Deal with the values starting with 0 first as they can be octal or - // hexadecimal numbers or even pointers. - if (s[0] == '0') { - if (Len(v) == 1) { - // This is just a lone 0, but it needs to be represented differently - // in Python depending on whether it's a zero or a null pointer. - if (SwigType_ispointer(resolved_type)) - result = NewString("None"); - else - result = v; - } else if (s[1] == 'x' || s[1] == 'X') { - // This must have been a hex number, we can use it directly in Python, - // so nothing to do here. - } else { - // This must have been an octal number, we have to change its prefix - // to be "0o" in Python 3 only (and as long as we still support Python - // 2.5, this can't be done unconditionally). - if (py3) { - if (end - s > 1) { - result = NewString("0o"); - Append(result, NewStringWithSize(s + 1, (int)(end - s - 1))); - } - } - } - } - - // Avoid unnecessary string allocation in the common case when we don't - // need to remove any suffix. - if (!result) - result = *end == '\0' ? v : NewStringWithSize(s, (int)(end - s)); - } - } - } - } - - // Check if this is a floating point number (notice that it wasn't - // necessarily parsed as a long above, consider e.g. ".123"). - if (!fail && !result) { + result = convertIntegerValue(v, resolved_type); + if (!result) { result = convertDoubleValue(v); if (!result) { - if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0) + if (Strcmp(v, "true") == 0) result = NewString("True"); - else if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0) + else if (Strcmp(v, "false") == 0) result = NewString("False"); - else if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0) { - if (!resolved_type) - resolved_type = SwigType_typedef_resolve_all(type); + else if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0) result = SwigType_ispointer(resolved_type) ? NewString("None") : NewString("0"); - } - // This could also be an enum type, default value of which could be // representable in Python if it doesn't include any scope (which could, // but currently is not, translated). @@ -2171,7 +2096,7 @@ public: Node *lookup = Swig_symbol_clookup(v, 0); if (lookup) { if (Cmp(Getattr(lookup, "nodeType"), "enumitem") == 0) - result = Getattr(lookup, "sym:name"); + result = Copy(Getattr(lookup, "sym:name")); } } } @@ -2218,10 +2143,12 @@ public: if (Getattr(p, "tmap:default")) return false; - if (String *value = Getattr(p, "value")) { - String *type = Getattr(p, "type"); - if (!convertValue(value, type)) + String *value = Getattr(p, "value"); + if (value) { + String *convertedValue = convertValue(value, Getattr(p, "type")); + if (!convertedValue) return false; + Delete(convertedValue); } } @@ -2233,7 +2160,7 @@ public: * is_real_overloaded() * * Check if the function is overloaded, but not just have some - * siblings generated due to the original function have + * siblings generated due to the original function having * default arguments. * ------------------------------------------------------------ */ bool is_real_overloaded(Node *n) { @@ -2246,7 +2173,7 @@ public: while (i) { Node *nn = Getattr(i, "defaultargs"); if (nn != h) { - /* Check if overloaded function has defaultargs and + /* Check if overloaded function has defaultargs and * pointed to the first overloaded. */ return true; } @@ -2262,13 +2189,16 @@ public: * Generate parameter list for Python functions or methods, * reuse make_autodocParmList() to do so. * ------------------------------------------------------------ */ - String *make_pyParmList(Node *n, bool in_class, bool is_calling, int kw) { - /* Get the original function for a defaultargs copy, + String *make_pyParmList(Node *n, bool in_class, bool is_calling, int kw, bool has_self_for_count = false) { + /* Get the original function for a defaultargs copy, * see default_arguments() in parser.y. */ Node *nn = Getattr(n, "defaultargs"); if (nn) n = nn; + Parm *parms = Getattr(n, "parms"); + int varargs = parms ? emit_isvarargs(parms) : 0; + /* We prefer to explicitly list all parameters of the C function in the generated Python code as this makes the function more convenient to use, however in some cases we must replace the real parameters list with just @@ -2278,8 +2208,9 @@ public: 2. We were explicitly asked to use the "compact" arguments form. 3. We were explicitly asked to use default args from C via the "python:cdefaultargs" feature. 4. One of the default argument values can't be represented in Python. + 5. Varargs that haven't been forced to use a fixed number of arguments with %varargs. */ - if (is_real_overloaded(n) || GetFlag(n, "feature:compactdefaultargs") || GetFlag(n, "feature:python:cdefaultargs") || !is_representable_as_pyargs(n)) { + if (is_real_overloaded(n) || GetFlag(n, "feature:compactdefaultargs") || GetFlag(n, "feature:python:cdefaultargs") || !is_representable_as_pyargs(n) || varargs) { String *parms = NewString(""); if (in_class) Printf(parms, "self, "); @@ -2291,7 +2222,7 @@ public: bool funcanno = py3 ? true : false; String *params = NewString(""); - String *_params = make_autodocParmList(n, false, is_calling, funcanno); + String *_params = make_autodocParmList(n, false, ((in_class || has_self_for_count)? 2 : 1), is_calling, funcanno); if (in_class) { Printf(params, "self"); @@ -2370,7 +2301,7 @@ public: * ------------------------------------------------------------ */ bool have_addtofunc(Node *n) { - return have_pythonappend(n) || have_pythonprepend(n) || have_docstring(n); + return have_pythonappend(n) || have_pythonprepend(n); } @@ -2420,21 +2351,28 @@ public: void emitFunctionShadowHelper(Node *n, File *f_dest, String *name, int kw) { String *parms = make_pyParmList(n, false, false, kw); String *callParms = make_pyParmList(n, false, true, kw); - /* Make a wrapper function to insert the code into */ - Printv(f_dest, "\ndef ", name, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL); - if (have_docstring(n)) - Printv(f_dest, tab4, docstring(n, AUTODOC_FUNC, tab4), "\n", NIL); - if (have_pythonprepend(n)) - Printv(f_dest, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL); - if (have_pythonappend(n)) { - Printv(f_dest, tab4 "val = ", funcCall(name, callParms), "\n", NIL); - Printv(f_dest, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL); - Printv(f_dest, tab4 "return val\n", NIL); - } else { - Printv(f_dest, tab4 "return ", funcCall(name, callParms), "\n", NIL); + + // Callbacks need the C function in order to extract the pointer from the swig_ptr: string + bool fast = (fastproxy && !have_addtofunc(n)) || Getattr(n, "feature:callback"); + + if (!fast || olddefs) { + /* Make a wrapper function to insert the code into */ + Printv(f_dest, "\n", "def ", name, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL); + if (have_docstring(n)) + Printv(f_dest, tab4, docstring(n, AUTODOC_FUNC, tab4, true), "\n", NIL); + if (have_pythonprepend(n)) + Printv(f_dest, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL); + if (have_pythonappend(n)) { + Printv(f_dest, tab4 "val = ", funcCall(name, callParms), "\n", NIL); + Printv(f_dest, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL); + Printv(f_dest, tab4 "return val\n", NIL); + } else { + Printv(f_dest, tab4 "return ", funcCall(name, callParms), "\n", NIL); + } } - if (!have_addtofunc(n)) { + // Below may result in a 2nd definition of the method when -olddefs is used. The Python interpreter will use the second definition as it overwrites the first. + if (fast) { /* If there is no addtofunc directive then just assign from the extension module (for speed up) */ Printv(f_dest, name, " = ", module, ".", name, "\n", NIL); } @@ -2458,36 +2396,64 @@ public: * add_method() * ------------------------------------------------------------ */ - void add_method(String *name, String *function, int kw, Node *n = 0, int funpack= 0, int num_required= -1, int num_arguments = -1) { + void add_method(String *name, String *function, int kw, Node *n = 0, int funpack = 0, int num_required = -1, int num_arguments = -1) { + String * meth_str = NewString(""); if (!kw) { - if (n && funpack) { + if (funpack) { if (num_required == 0 && num_arguments == 0) { - Printf(methods, "\t { (char *)\"%s\", (PyCFunction)%s, METH_NOARGS, ", name, function); + Printf(meth_str, "\t { \"%s\", %s, METH_NOARGS, ", name, function); } else if (num_required == 1 && num_arguments == 1) { - Printf(methods, "\t { (char *)\"%s\", (PyCFunction)%s, METH_O, ", name, function); + Printf(meth_str, "\t { \"%s\", %s, METH_O, ", name, function); } else { - Printf(methods, "\t { (char *)\"%s\", %s, METH_VARARGS, ", name, function); + Printf(meth_str, "\t { \"%s\", %s, METH_VARARGS, ", name, function); } } else { - Printf(methods, "\t { (char *)\"%s\", %s, METH_VARARGS, ", name, function); + Printf(meth_str, "\t { \"%s\", %s, METH_VARARGS, ", name, function); } } else { - Printf(methods, "\t { (char *)\"%s\", (PyCFunction) %s, METH_VARARGS | METH_KEYWORDS, ", name, function); + // Cast via void(*)(void) to suppress GCC -Wcast-function-type warning. + // Python should always call the function correctly, but the Python C API + // requires us to store it in function pointer of a different type. + Printf(meth_str, "\t { \"%s\", (PyCFunction)(void(*)(void))%s, METH_VARARGS|METH_KEYWORDS, ", name, function); } + Append(methods, meth_str); + if (fastproxy) { + Append(methods_proxydocs, meth_str); + } + Delete(meth_str); if (!n) { Append(methods, "NULL"); + if (fastproxy) { + Append(methods_proxydocs, "NULL"); + } } else if (have_docstring(n)) { - String *ds = cdocstring(n, AUTODOC_FUNC); - Printf(methods, "(char *)\"%s\"", ds); + /* Use the low-level docstring here since this is the docstring that will be used for the C API */ + String *ds = cdocstring(n, Getattr(n, "memberfunction") ? AUTODOC_METHOD : AUTODOC_FUNC, true); + Printf(methods, "\"%s\"", ds); + if (fastproxy) { + /* In the fastproxy case, we must also record the high-level docstring for use in the Python shadow API */ + Delete(ds); + ds = cdocstring(n, Getattr(n, "memberfunction") ? AUTODOC_METHOD : AUTODOC_FUNC); + Printf(methods_proxydocs, "\"%s\"", ds); + } Delete(ds); } else if (Getattr(n, "feature:callback")) { - Printf(methods, "(char *)\"swig_ptr: %s\"", Getattr(n, "feature:callback:name")); + Printf(methods, "\"swig_ptr: %s\"", Getattr(n, "feature:callback:name")); + if (fastproxy) { + Printf(methods_proxydocs, "\"swig_ptr: %s\"", Getattr(n, "feature:callback:name")); + } } else { Append(methods, "NULL"); + if (fastproxy) { + Append(methods_proxydocs, "NULL"); + } } Append(methods, "},\n"); + if (fastproxy) { + Append(methods_proxydocs, "},\n"); + } } /* ------------------------------------------------------------ @@ -2502,12 +2468,24 @@ public: String *tmp = NewString(""); String *dispatch; - const char *dispatch_code = funpack ? "return %s(self, argc, argv);" : "return %s(self, args);"; + + const char *dispatch_call = funpack ? "%s(self, argc, argv);" : (builtin_ctor ? "%s(self, args, NULL);" : "%s(self, args);"); + String *dispatch_code = NewStringf("return %s", dispatch_call); if (castmode) { dispatch = Swig_overload_dispatch_cast(n, dispatch_code, &maxargs); } else { - dispatch = Swig_overload_dispatch(n, dispatch_code, &maxargs); + String *fastdispatch_code; + if (builtin_ctor) + fastdispatch_code = NewStringf("int retval = %s\nif (retval == 0 || !SWIG_Python_TypeErrorOccurred(NULL)) return retval;\nSWIG_fail;", dispatch_call); + else + fastdispatch_code = NewStringf("PyObject *retobj = %s\nif (!SWIG_Python_TypeErrorOccurred(retobj)) return retobj;\nSWIG_fail;", dispatch_call); + if (!CPlusPlus) { + Insert(fastdispatch_code, 0, "{\n"); + Append(fastdispatch_code, "\n}"); + } + dispatch = Swig_overload_dispatch(n, dispatch_code, &maxargs, fastdispatch_code); + Delete(fastdispatch_code); } /* Generate a dispatch wrapper for all overloaded functions */ @@ -2516,7 +2494,8 @@ public: String *symname = Getattr(n, "sym:name"); String *wname = Swig_name_wrapper(symname); - Printv(f->def, linkage, builtin_ctor ? "int " : "PyObject *", wname, "(PyObject *self, PyObject *args) {", NIL); + const char *builtin_kwargs = builtin_ctor ? ", PyObject *SWIGUNUSEDPARM(kwargs)" : ""; + Printv(f->def, linkage, builtin_ctor ? "int " : "PyObject *", wname, "(PyObject *self, PyObject *args", builtin_kwargs, ") {", NIL); Wrapper_add_local(f, "argc", "Py_ssize_t argc"); Printf(tmp, "PyObject *argv[%d] = {0}", maxargs + 1); @@ -2524,9 +2503,14 @@ public: if (!fastunpack) { Wrapper_add_local(f, "ii", "Py_ssize_t ii"); - if (maxargs - (add_self ? 1 : 0) > 0) - Append(f->code, "if (!PyTuple_Check(args)) SWIG_fail;\n"); - Append(f->code, "argc = args ? PyObject_Length(args) : 0;\n"); + + if (maxargs - (add_self ? 1 : 0) > 0) { + Append(f->code, "if (!PyTuple_Check(args)) SWIG_fail;\n"); + Append(f->code, "argc = PyObject_Length(args);\n"); + } else { + Append(f->code, "argc = args ? PyObject_Length(args) : 0;\n"); + } + if (add_self) Append(f->code, "argv[0] = self;\n"); Printf(f->code, "for (ii = 0; (ii < %d) && (ii < argc); ii++) {\n", add_self ? maxargs - 1 : maxargs); @@ -2536,7 +2520,7 @@ public: Append(f->code, "argc++;\n"); } else { String *iname = Getattr(n, "sym:name"); - Printf(f->code, "if (!(argc = SWIG_Python_UnpackTuple(args,\"%s\",0,%d,argv%s))) SWIG_fail;\n", iname, maxargs, add_self ? "+1" : ""); + Printf(f->code, "if (!(argc = SWIG_Python_UnpackTuple(args, \"%s\", 0, %d, argv%s))) SWIG_fail;\n", iname, maxargs, add_self ? "+1" : ""); if (add_self) Append(f->code, "argv[0] = self;\n"); else @@ -2549,8 +2533,8 @@ public: if (GetFlag(n, "feature:python:maybecall")) { Append(f->code, "fail:\n"); - Append(f->code, "Py_INCREF(Py_NotImplemented);\n"); - Append(f->code, "return Py_NotImplemented;\n"); + Append(f->code, " Py_INCREF(Py_NotImplemented);\n"); + Append(f->code, " return Py_NotImplemented;\n"); } else { Node *sibl = n; while (Getattr(sibl, "sym:previousSibling")) @@ -2562,7 +2546,7 @@ public: Delete(fulldecl); } while ((sibl = Getattr(sibl, "sym:nextSibling"))); Append(f->code, "fail:\n"); - Printf(f->code, "SWIG_SetErrorMsg(PyExc_NotImplementedError," + Printf(f->code, " SWIG_Python_RaiseOrModifyTypeError(" "\"Wrong number or type of arguments for overloaded function '%s'.\\n\"" "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes); Printf(f->code, "return %s;\n", builtin_ctor ? "-1" : "0"); Delete(protoTypes); @@ -2579,6 +2563,7 @@ public: } DelWrapper(f); Delete(dispatch); + Delete(dispatch_code); Delete(tmp); Delete(wname); } @@ -2671,12 +2656,12 @@ public: builtin_self = false; else builtin_ctor = true; + Delete(mrename); } bool director_class = (getCurrentClass() && Swig_directorclass(getCurrentClass())); bool add_self = builtin_self && (!builtin_ctor || director_class); bool builtin_getter = (builtin && GetFlag(n, "memberget")); bool builtin_setter = (builtin && GetFlag(n, "memberset") && !builtin_getter); - bool over_varargs = false; char const *self_param = builtin ? "self" : "SWIGUNUSEDPARM(self)"; char const *wrap_return = builtin_ctor ? "int " : "PyObject *"; String *linkage = NewString("SWIGINTERN "); @@ -2725,9 +2710,10 @@ public: Append(wname, overname); } + const char *builtin_kwargs = builtin_ctor ? ", PyObject *SWIGUNUSEDPARM(kwargs)" : ""; if (!allow_kwargs || overname) { if (!varargs) { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL); } else { Printv(f->def, linkage, wrap_return, wname, "__varargs__", "(PyObject *", self_param, ", PyObject *args, PyObject *varargs) {", NIL); } @@ -2744,53 +2730,33 @@ public: } if (!builtin || !in_class || tuple_arguments > 0) { if (!allow_kwargs) { - Append(parse_args, " if (!PyArg_ParseTuple(args,(char *)\""); + Append(parse_args, " if (!PyArg_ParseTuple(args, \""); } else { - Append(parse_args, " if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)\""); - Append(arglist, ",kwnames"); + Append(parse_args, " if (!PyArg_ParseTupleAndKeywords(args, kwargs, \""); + Append(arglist, ", kwnames"); } } - if (overname) { - String *over_varargs_attr = Getattr(n, "python:overvarargs"); - if (!over_varargs_attr) { - for (Node *sibling = n; sibling; sibling = Getattr(sibling, "sym:nextSibling")) { - if (emit_isvarargs(Getattr(sibling, "parms"))) { - over_varargs = true; - break; - } - } - over_varargs_attr = NewString(over_varargs ? "1" : "0"); - for (Node *sibling = n; sibling; sibling = Getattr(sibling, "sym:nextSibling")) - Setattr(sibling, "python:overvarargs", over_varargs_attr); - } - if (Strcmp(over_varargs_attr, "0") != 0) - over_varargs = true; - } + bool over_varargs = emit_isvarargs_function(n); - int funpack = modernargs && fastunpack && !varargs && !over_varargs && !allow_kwargs; + int funpack = fastunpack && !varargs && !over_varargs && !allow_kwargs; int noargs = funpack && (tuple_required == 0 && tuple_arguments == 0); int onearg = funpack && (tuple_required == 1 && tuple_arguments == 1); - if (builtin && funpack && !overname && !builtin_ctor && - !(GetFlag(n, "feature:compactdefaultargs") && (tuple_arguments > tuple_required || varargs))) { - String *argattr = NewStringf("%d", tuple_arguments); - Setattr(n, "python:argcount", argattr); - Delete(argattr); + if (builtin && funpack && !overname && !builtin_ctor) { + int compactdefargs = ParmList_is_compactdefargs(l); + if (!(compactdefargs && (tuple_arguments > tuple_required || varargs))) { + String *argattr = NewStringf("%d", tuple_arguments); + Setattr(n, "python:argcount", argattr); + Delete(argattr); + } } /* Generate code for argument marshalling */ if (funpack) { - if (overname) { - if (aliasobj0) { - Append(f->code, "#define obj0 (swig_obj[0])\n"); - } - } else if (num_arguments) { + if (num_arguments > 0 && !overname) { sprintf(source, "PyObject *swig_obj[%d]", num_arguments); Wrapper_add_localv(f, "swig_obj", source, NIL); - if (aliasobj0) { - Append(f->code, "#define obj0 (swig_obj[0])\n"); - } } } @@ -2835,7 +2801,7 @@ public: sprintf(source, "obj%d", builtin_ctor ? i + 1 : i); if (parse_from_tuple) { - Putc(',', arglist); + Printf(arglist, ", "); if (i == num_required) Putc('|', parse_args); /* Optional argument separator */ } @@ -2843,7 +2809,7 @@ public: /* Keyword argument handling */ if (allow_kwargs && parse_from_tuple) { String *name = makeParameterName(n, p, i + 1); - Printf(kwargs, "(char *) \"%s\",", name); + Printf(kwargs, " (char *)\"%s\", ", name); Delete(name); } @@ -2908,12 +2874,12 @@ public: /* finish argument marshalling */ Append(kwargs, " NULL }"); if (allow_kwargs) { - Printv(f->locals, " char * kwnames[] = ", kwargs, ";\n", NIL); + Printv(f->locals, " char * kwnames[] = ", kwargs, ";\n", NIL); } if (builtin && !funpack && in_class && tuple_arguments == 0) { Printf(parse_args, " if (args && PyTuple_Check(args) && PyTuple_GET_SIZE(args) > 0) SWIG_exception_fail(SWIG_TypeError, \"%s takes no arguments\");\n", iname); - } else if (use_parse || allow_kwargs || !modernargs) { + } else if (use_parse || allow_kwargs) { Printf(parse_args, ":%s\"", iname); Printv(parse_args, arglist, ")) SWIG_fail;\n", NIL); funpack = 0; @@ -2923,28 +2889,25 @@ public: Clear(f->def); if (overname) { if (noargs) { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL); } else { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **swig_obj) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **swig_obj) {", NIL); } Printf(parse_args, "if ((nobjs < %d) || (nobjs > %d)) SWIG_fail;\n", num_required, num_arguments); } else { - if (noargs) { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); - } else { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); - } - if (onearg && !builtin_ctor) { + int is_tp_call = Equal(Getattr(n, "feature:python:slot"), "tp_call"); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL); + if (onearg && !builtin_ctor && !is_tp_call) { Printf(parse_args, "if (!args) SWIG_fail;\n"); Append(parse_args, "swig_obj[0] = args;\n"); } else if (!noargs) { - Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args,\"%s\",%d,%d,swig_obj)) SWIG_fail;\n", iname, num_fixed_arguments, tuple_arguments); + Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args, \"%s\", %d, %d, swig_obj)) SWIG_fail;\n", iname, num_fixed_arguments, tuple_arguments); } else if (noargs) { - Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args,\"%s\",%d,%d,0)) SWIG_fail;\n", iname, num_fixed_arguments, tuple_arguments); + Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args, \"%s\", %d, %d, 0)) SWIG_fail;\n", iname, num_fixed_arguments, tuple_arguments); } } } else { - Printf(parse_args, "if(!PyArg_UnpackTuple(args,(char *)\"%s\",%d,%d", iname, num_fixed_arguments, tuple_arguments); + Printf(parse_args, "if (!PyArg_UnpackTuple(args, \"%s\", %d, %d", iname, num_fixed_arguments, tuple_arguments); Printv(parse_args, arglist, ")) SWIG_fail;\n", NIL); } } @@ -3009,9 +2972,9 @@ public: } /* if the object is a director, and the method call originated from its - * underlying python object, resolve the call by going up the c++ - * inheritance chain. otherwise try to resolve the method in python. - * without this check an infinite loop is set up between the director and + * underlying python object, resolve the call by going up the c++ + * inheritance chain. otherwise try to resolve the method in python. + * without this check an infinite loop is set up between the director and * shadow class method calls. */ @@ -3105,7 +3068,7 @@ public: // base class pointers! /* New addition to unwrap director return values so that the original - * python object is returned instead. + * python object is returned instead. */ #if 1 int unwrap = 0; @@ -3187,21 +3150,18 @@ public: if (need_cleanup) { Printv(f->code, cleanup, NIL); } - if (builtin_ctor) + if (builtin_ctor) { Printv(f->code, " return -1;\n", NIL); - else - Printv(f->code, " return NULL;\n", NIL); - - - if (funpack) { - if (aliasobj0) { - Append(f->code, "#if defined(obj0)\n"); - Append(f->code, "#undef obj0\n"); - Append(f->code, "#endif\n"); + } else { + if (GetFlag(n, "feature:python:maybecall")) { + Append(f->code, " PyErr_Clear();\n"); + Append(f->code, " Py_INCREF(Py_NotImplemented);\n"); + Append(f->code, " return Py_NotImplemented;\n"); + } else { + Printv(f->code, " return NULL;\n", NIL); } } - Append(f->code, "}\n"); /* Substitute the cleanup code */ @@ -3227,9 +3187,10 @@ public: DelWrapper(f); f = NewWrapper(); if (funpack) { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **swig_obj) {", NIL); + // Note: funpack is currently always false for varargs + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **swig_obj) {", NIL); } else { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL); } Wrapper_add_local(f, "resultobj", builtin_ctor ? "int resultobj" : "PyObject *resultobj"); Wrapper_add_local(f, "varargs", "PyObject *varargs"); @@ -3292,6 +3253,10 @@ public: Delete(h); } Setattr(h, "getter", "SwigPyObject_get___dict__"); + if (!Getattr(h, "doc")) { + Setattr(n, "doc:high:name", Getattr(n, "name")); + Setattr(h, "doc", cdocstring(n, AUTODOC_VAR)); + } } if (builtin_getter) { @@ -3306,6 +3271,12 @@ public: } Setattr(h, "getter", wrapper_name); Delattr(n, "memberget"); + if (!Getattr(h, "doc")) { + Setattr(n, "doc:high:name", Getattr(n, "name")); + String *ds = cdocstring(n, AUTODOC_VAR); + Setattr(h, "doc", ds); + Delete(ds); + } } if (builtin_setter) { String *memname = Getattr(n, "membervariableHandler:sym:name"); @@ -3319,6 +3290,12 @@ public: } Setattr(h, "setter", wrapper_name); Delattr(n, "memberset"); + if (!Getattr(h, "doc")) { + Setattr(n, "doc:high:name", Getattr(n, "name")); + String *ds = cdocstring(n, AUTODOC_VAR); + Setattr(h, "doc", ds); + Delete(ds); + } } if (in_class && builtin) { @@ -3328,15 +3305,18 @@ public: String *func_type = Getattr(n, "feature:python:slot:functype"); String *closure_decl = getClosure(func_type, wrapper_name, overname ? 0 : funpack); String *feature_name = NewStringf("feature:python:%s", slot); - String *closure_name = Copy(wrapper_name); + String *closure_name = 0; if (closure_decl) { - Append(closure_name, "_closure"); - if (!Getattr(n, "sym:overloaded") || !Getattr(n, "sym:nextSibling")) - Printf(f_wrappers, "%s /* defines %s */\n\n", closure_decl, closure_name); + closure_name = NewStringf("%s_%s_closure", wrapper_name, func_type); + if (!GetFlag(builtin_closures, closure_name)) + Printf(builtin_closures_code, "%s /* defines %s */\n\n", closure_decl, closure_name); + SetFlag(builtin_closures, closure_name); Delete(closure_decl); + } else { + closure_name = Copy(wrapper_name); } if (func_type) { - String *s = NewStringf("(%s) %s", func_type, closure_name); + String *s = NewStringf("%s", closure_name); Delete(closure_name); closure_name = s; } @@ -3393,7 +3373,17 @@ public: Python dictionary. */ if (!have_globals) { - Printf(f_init, "\t PyDict_SetItemString(md,(char *)\"%s\", SWIG_globals());\n", global_name); + Printf(f_init, "\t globals = SWIG_globals();\n"); + Printf(f_init, "\t if (!globals) {\n"); + Printf(f_init, " PyErr_SetString(PyExc_TypeError, \"Failure to create SWIG globals.\");\n"); + Printf(f_init, "#if PY_VERSION_HEX >= 0x03000000\n"); + Printf(f_init, "\t return NULL;\n"); + Printf(f_init, "#else\n"); + Printf(f_init, "\t return;\n"); + Printf(f_init, "#endif\n"); + Printf(f_init, "\t }\n"); + Printf(f_init, "\t PyDict_SetItemString(md, \"%s\", globals);\n", global_name); + Printf(f_init, "\t Py_DECREF(globals);\n"); if (builtin) Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", global_name); have_globals = 1; @@ -3481,9 +3471,9 @@ public: Wrapper_print(getf, f_wrappers); /* Now add this to the variable linking mechanism */ - Printf(f_init, "\t SWIG_addvarlink(SWIG_globals(),(char *)\"%s\",%s, %s);\n", iname, vargetname, varsetname); + Printf(f_init, "\t SWIG_addvarlink(globals, \"%s\", %s, %s);\n", iname, vargetname, varsetname); if (builtin && shadow && !assignable && !in_class) { - Printf(f_init, "\t PyDict_SetItemString(md, (char *)\"%s\", PyObject_GetAttrString(SWIG_globals(), \"%s\"));\n", iname, iname); + Printf(f_init, "\t PyDict_SetItemString(md, \"%s\", PyObject_GetAttrString(globals, \"%s\"));\n", iname, iname); Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", iname); } Delete(vargetname); @@ -3509,7 +3499,7 @@ public: /* Note, that we need special handling for function pointers, as * SwigType_base(fptr) does not return the underlying pointer-to-function * type but the return-type of function. */ - if(!SwigType_isfunction(uqtype) && !SwigType_isfunctionpointer(uqtype)) { + if (!SwigType_isfunction(uqtype) && !SwigType_isfunctionpointer(uqtype)) { SwigType *basetype = SwigType_base(uqtype); result = SwigType_isclass(basetype) != 0; Delete(basetype); @@ -3575,15 +3565,7 @@ public: Printf(f_wrappers, "SWIGINTERN PyObject *%s_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", iname); Printf(f_wrappers, tab2 "PyObject *module;\n", tm); Printf(f_wrappers, tab2 "PyObject *d;\n"); - if (modernargs) { - if (fastunpack) { - Printf(f_wrappers, tab2 "if (!SWIG_Python_UnpackTuple(args,(char *)\"swigconstant\", 1, 1,&module)) return NULL;\n"); - } else { - Printf(f_wrappers, tab2 "if (!PyArg_UnpackTuple(args,(char *)\"swigconstant\", 1, 1,&module)) return NULL;\n"); - } - } else { - Printf(f_wrappers, tab2 "if (!PyArg_ParseTuple(args,(char *)\"O:swigconstant\", &module)) return NULL;\n"); - } + Printf(f_wrappers, tab2 "if (!SWIG_Python_UnpackTuple(args, \"swigconstant\", 1, 1, &module)) return NULL;\n"); Printf(f_wrappers, tab2 "d = PyModule_GetDict(module);\n"); Printf(f_wrappers, tab2 "if (!d) return NULL;\n"); Printf(f_wrappers, tab2 "%s\n", tm); @@ -3592,7 +3574,7 @@ public: // Register the method in SwigMethods array String *cname = NewStringf("%s_swigconstant", iname); - add_method(cname, cname, 0); + add_method(cname, cname, 0, 0, 1, 1, 1); Delete(cname); } else { Printf(f_init, "%s\n", tm); @@ -3610,27 +3592,28 @@ public: } if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) { + String *f_s; if (!in_class) { - if(needs_swigconstant(n)) { - Printv(f_shadow, "\n",NIL); - Printv(f_shadow, module, ".", iname, "_swigconstant(",module,")\n", NIL); - } - Printv(f_shadow, iname, " = ", module, ".", iname, "\n", NIL); + f_s = f_shadow; } else { - if (!(Getattr(n, "feature:python:callback"))) { - if(needs_swigconstant(n)) { - Printv(f_shadow_stubs, "\n",NIL); - Printv(f_shadow_stubs, module, ".", iname, "_swigconstant(", module, ")\n", NIL); - } - Printv(f_shadow_stubs, iname, " = ", module, ".", iname, "\n", NIL); + f_s = Getattr(n, "feature:python:callback") ? NIL : f_shadow_stubs; + } + + if (f_s) { + if (needs_swigconstant(n)) { + Printv(f_s, "\n",NIL); + Printv(f_s, module, ".", iname, "_swigconstant(",module,")\n", NIL); } + Printv(f_s, iname, " = ", module, ".", iname, "\n", NIL); + if (have_docstring(n)) + Printv(f_s, docstring(n, AUTODOC_CONST, tab4), "\n", NIL); } } return SWIG_OK; } - /* ------------------------------------------------------------ + /* ------------------------------------------------------------ * nativeWrapper() * ------------------------------------------------------------ */ @@ -3665,7 +3648,7 @@ public: /* --------------------------------------------------------------- * classDirectorMethod() * - * Emit a virtual director method to pass a method call on to the + * Emit a virtual director method to pass a method call on to the * underlying Python object. * ** Moved down due to gcc-2.96 internal error ** * --------------------------------------------------------------- */ @@ -3702,7 +3685,7 @@ public: Wrapper *w = NewWrapper(); String *call; String *basetype = Getattr(parent, "classtype"); - String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); + String *target = Swig_method_decl(0, decl, classname, parms, 0); call = Swig_csuperclass_call(0, basetype, superparms); Printf(w->def, "%s::%s: %s, Swig::Director(self) { \n", classname, target, call); Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype); @@ -3715,7 +3698,7 @@ public: /* constructor header */ { - String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); + String *target = Swig_method_decl(0, decl, classname, parms, 1); Printf(f_directors_h, " %s;\n", target); Delete(target); } @@ -3837,7 +3820,7 @@ public: if (shadow) { if (builtin) { String *rname = SwigType_namestr(real_classname); - Printf(builtin_methods, " { \"__disown__\", (PyCFunction) Swig::Director::swig_pyobj_disown< %s >, METH_NOARGS, \"\" },\n", rname); + Printf(builtin_methods, " { \"__disown__\", Swig::Director::swig_pyobj_disown< %s >, METH_NOARGS, \"\" },\n", rname); Delete(rname); } else { String *symname = Getattr(n, "sym:name"); @@ -3849,7 +3832,7 @@ public: Printv(f_shadow, tab8, "self.this.disown()\n", NIL); #endif Printv(f_shadow, tab8, module, ".", mrename, "(self)\n", NIL); - Printv(f_shadow, tab8, "return weakref_proxy(self)\n", NIL); + Printv(f_shadow, tab8, "return weakref.proxy(self)\n", NIL); Delete(mrename); } } @@ -3917,9 +3900,15 @@ public: String *mname = SwigType_manglestr(rname); String *pmname = SwigType_manglestr(pname); String *templ = NewStringf("SwigPyBuiltin_%s", mname); - int funpack = modernargs && fastunpack; + int funpack = fastunpack; + static String *tp_new = NewString("PyType_GenericNew"); Printv(f_init, " SwigPyBuiltin_SetMetaType(builtin_pytype, metatype);\n", NIL); + + // We can’t statically initialize a structure member with a function defined in another C module + // So this is done in the initialization function instead, see https://docs.python.org/2/extending/newtypes.html + Printf(f_init, " builtin_pytype->tp_new = %s;\n", getSlot(n, "feature:python:tp_new", tp_new)); + Printv(f_init, " builtin_base_count = 0;\n", NIL); List *baselist = Getattr(n, "bases"); if (baselist) { @@ -3977,9 +3966,10 @@ public: const char *setter_closure = setter ? funpack ? "SwigPyBuiltin_FunpackSetterClosure" : "SwigPyBuiltin_SetterClosure" : "0"; String *gspair = NewStringf("%s_%s_getset", symname, memname); Printf(f, "static SwigPyGetSet %s = { %s, %s };\n", gspair, getter ? getter : "0", setter ? setter : "0"); - String *entry = - NewStringf("{ (char *) \"%s\", (getter) %s, (setter) %s, (char *)\"%s.%s\", (void *) &%s }\n", memname, getter_closure, - setter_closure, name, memname, gspair); + String *doc = Getattr(mgetset, "doc"); + if (!doc) + doc = NewStringf("%s.%s", name, memname); + String *entry = NewStringf("{ (char *)\"%s\", %s, %s, (char *)\"%s\", &%s }", memname, getter_closure, setter_closure, doc, gspair); if (GetFlag(mgetset, "static")) { Printf(f, "static PyGetSetDef %s_def = %s;\n", gspair, entry); Printf(f_init, "static_getset = SwigPyStaticVar_new_getset(metatype, &%s_def);\n", gspair); @@ -3991,7 +3981,7 @@ public: Delete(gspair); Delete(entry); } - Printv(f, getset_def, " {NULL, NULL, NULL, NULL, NULL} /* Sentinel */\n", "};\n\n", NIL); + Printv(f, getset_def, " { NULL, NULL, NULL, NULL, NULL } /* Sentinel */\n", "};\n\n", NIL); // Rich compare function Hash *richcompare = Getattr(n, "python:richcompare"); @@ -4057,7 +4047,6 @@ public: static String *tp_basicsize = NewStringf("sizeof(SwigPyObject)"); static String *tp_dictoffset_default = NewString("offsetof(SwigPyObject, dict)"); - static String *tp_new = NewString("PyType_GenericNew"); static String *tp_hash = NewString("SwigPyObject_hash"); String *tp_as_number = NewStringf("&%s_type.as_number", templ); String *tp_as_sequence = NewStringf("&%s_type.as_sequence", templ); @@ -4101,7 +4090,16 @@ public: Printv(f, "#else\n", NIL); printSlot(f, getSlot(n, "feature:python:tp_flags", tp_flags), "tp_flags"); Printv(f, "#endif\n", NIL); - printSlot(f, quoted_tp_doc_str, "tp_doc"); + if (have_docstring(n)) { + String *ds = cdocstring(n, AUTODOC_CLASS); + String *tp_doc = NewString(""); + Printf(tp_doc, "\"%s\"", ds); + Delete(ds); + printSlot(f, tp_doc, "tp_doc"); + Delete(tp_doc); + } else { + printSlot(f, quoted_tp_doc_str, "tp_doc"); + } printSlot(f, getSlot(n, "feature:python:tp_traverse"), "tp_traverse", "traverseproc"); printSlot(f, getSlot(n, "feature:python:tp_clear"), "tp_clear", "inquiry"); printSlot(f, getSlot(n, "feature:python:tp_richcompare", richcompare_func), "tp_richcompare", "richcmpfunc"); @@ -4118,7 +4116,7 @@ public: printSlot(f, getSlot(n, "feature:python:tp_dictoffset", tp_dictoffset_default), "tp_dictoffset", "Py_ssize_t"); printSlot(f, getSlot(n, "feature:python:tp_init", tp_init), "tp_init", "initproc"); printSlot(f, getSlot(n, "feature:python:tp_alloc"), "tp_alloc", "allocfunc"); - printSlot(f, getSlot(n, "feature:python:tp_new", tp_new), "tp_new", "newfunc"); + printSlot(f, getSlot(), "tp_new", "newfunc"); printSlot(f, getSlot(n, "feature:python:tp_free"), "tp_free", "freefunc"); printSlot(f, getSlot(n, "feature:python:tp_is_gc"), "tp_is_gc", "inquiry"); printSlot(f, getSlot(n, "feature:python:tp_bases"), "tp_bases", "PyObject *"); @@ -4127,9 +4125,7 @@ public: printSlot(f, getSlot(n, "feature:python:tp_subclasses"), "tp_subclasses", "PyObject *"); printSlot(f, getSlot(n, "feature:python:tp_weaklist"), "tp_weaklist", "PyObject *"); printSlot(f, getSlot(n, "feature:python:tp_del"), "tp_del", "destructor"); - Printv(f, "#if PY_VERSION_HEX >= 0x02060000\n", NIL); printSlot(f, getSlot(n, "feature:python:tp_version_tag"), "tp_version_tag", "int"); - Printv(f, "#endif\n", NIL); Printv(f, "#if PY_VERSION_HEX >= 0x03040000\n", NIL); printSlot(f, getSlot(n, "feature:python:tp_finalize"), "tp_finalize", "destructor"); Printv(f, "#endif\n", NIL); @@ -4137,9 +4133,7 @@ public: printSlot(f, getSlot(n, "feature:python:tp_allocs"), "tp_allocs", "Py_ssize_t"); printSlot(f, getSlot(n, "feature:python:tp_frees"), "tp_frees", "Py_ssize_t"); printSlot(f, getSlot(n, "feature:python:tp_maxalloc"), "tp_maxalloc", "Py_ssize_t"); - Printv(f, "#if PY_VERSION_HEX >= 0x02050000\n", NIL); printSlot(f, getSlot(n, "feature:python:tp_prev"), "tp_prev"); - Printv(f, "#endif\n", NIL); printSlot(f, getSlot(n, "feature:python:tp_next"), "tp_next"); Printv(f, "#endif\n", NIL); Printf(f, " },\n"); @@ -4205,9 +4199,7 @@ public: printSlot(f, getSlot(n, "feature:python:nb_divide"), "nb_true_divide", "binaryfunc"); printSlot(f, getSlot(n, "feature:python:nb_inplace_floor_divide"), "nb_inplace_floor_divide", "binaryfunc"); printSlot(f, getSlot(n, "feature:python:nb_inplace_divide"), "nb_inplace_true_divide", "binaryfunc"); - Printv(f, "#if PY_VERSION_HEX >= 0x02050000\n", NIL); printSlot(f, getSlot(n, "feature:python:nb_index"), "nb_index", "unaryfunc"); - Printv(f, "#endif\n", NIL); Printv(f, "#if PY_VERSION_HEX >= 0x03050000\n", NIL); printSlot(f, getSlot(n, "feature:python:nb_matrix_multiply"), "nb_matrix_multiply", "binaryfunc"); printSlot(f, getSlot(n, "feature:python:nb_inplace_matrix_multiply"), "nb_inplace_matrix_multiply", "binaryfunc"); @@ -4251,10 +4243,8 @@ public: printSlot(f, getSlot(n, "feature:python:bf_getsegcount"), "bf_getsegcount", "segcountproc"); printSlot(f, getSlot(n, "feature:python:bf_getcharbuffer"), "bf_getcharbuffer", "charbufferproc"); Printv(f, "#endif\n", NIL); - Printv(f, "#if PY_VERSION_HEX >= 0x02060000\n", NIL); printSlot(f, getSlot(n, "feature:python:bf_getbuffer"), "bf_getbuffer", "getbufferproc"); printSlot(f, getSlot(n, "feature:python:bf_releasebuffer"), "bf_releasebuffer", "releasebufferproc"); - Printv(f, "#endif\n", NIL); Printf(f, " },\n"); // PyObject *ht_name, *ht_slots, *ht_qualname; @@ -4324,8 +4314,6 @@ public: } virtual int classHandler(Node *n) { - int oldclassic = classic; - int oldmodern = modern; File *f_shadow_file = f_shadow; Node *base_node = NULL; @@ -4335,19 +4323,6 @@ public: have_constructor = 0; have_repr = 0; - if (GetFlag(n, "feature:classic")) { - classic = 1; - modern = 0; - } - if (GetFlag(n, "feature:modern")) { - classic = 0; - modern = 1; - } - if (GetFlag(n, "feature:exceptionclass")) { - classic = 1; - modern = 0; - } - class_name = Getattr(n, "sym:name"); real_classname = Getattr(n, "name"); @@ -4413,9 +4388,9 @@ public: if (builtin) { if (have_docstring(n)) { - String *str = cdocstring(n, AUTODOC_CLASS); - Setattr(n, "feature:python:tp_doc", str); - Delete(str); + String *ds = cdocstring(n, AUTODOC_CLASS); + Setattr(n, "feature:python:tp_doc", ds); + Delete(ds); } else { String *name = Getattr(n, "name"); String *rname = add_explicit_scope(SwigType_namestr(name)); @@ -4423,52 +4398,37 @@ public: Delete(rname); } } else { + if (!py3) { + if (GetFlag(n, "feature:python:nondynamic")) + Printv(f_shadow, "@_swig_add_metaclass(_SwigNonDynamicMeta)\n", NIL); + } Printv(f_shadow, "class ", class_name, NIL); if (Len(base_class)) { Printf(f_shadow, "(%s)", base_class); } else { - if (!classic) { - Printf(f_shadow, modern ? "(object)" : "(_object)"); - } if (GetFlag(n, "feature:exceptionclass")) { Printf(f_shadow, "(Exception)"); + } else { + Printf(f_shadow, "(object"); + Printf(f_shadow, py3 && GetFlag(n, "feature:python:nondynamic") ? ", metaclass=_SwigNonDynamicMeta" : "", ")"); + Printf(f_shadow, ")"); } } Printf(f_shadow, ":\n"); + + // write docstrings if requested if (have_docstring(n)) { String *str = docstring(n, AUTODOC_CLASS, tab4); if (str && Len(str)) Printv(f_shadow, tab4, str, "\n\n", NIL); } - if (!modern) { - Printv(f_shadow, tab4, "__swig_setmethods__ = {}\n", NIL); - if (Len(base_class)) { - Printv(f_shadow, tab4, "for _s in [", base_class, "]:\n", tab8, "__swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))\n", NIL); - } - - if (!GetFlag(n, "feature:python:nondynamic")) { - Printv(f_shadow, tab4, "__setattr__ = lambda self, name, value: _swig_setattr(self, ", class_name, ", name, value)\n", NIL); - } else { - Printv(f_shadow, tab4, "__setattr__ = lambda self, name, value: _swig_setattr_nondynamic(self, ", class_name, ", name, value)\n", NIL); - } - - Printv(f_shadow, tab4, "__swig_getmethods__ = {}\n", NIL); - if (Len(base_class)) { - Printv(f_shadow, tab4, "for _s in [", base_class, "]:\n", tab8, "__swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))\n", NIL); - } - - Printv(f_shadow, tab4, "__getattr__ = lambda self, name: _swig_getattr(self, ", class_name, ", name)\n", NIL); - } else { - Printv(f_shadow, tab4, "thisown = _swig_property(lambda x: x.this.own(), ", "lambda x, v: x.this.own(v), doc='The membership flag')\n", NIL); - /* Add static attribute */ - if (GetFlag(n, "feature:python:nondynamic")) { - Printv(f_shadow_file, - tab4, "__setattr__ = _swig_setattr_nondynamic_method(object.__setattr__)\n", - tab4, "class __metaclass__(type):\n", tab4, tab4, "__setattr__ = _swig_setattr_nondynamic_method(type.__setattr__)\n", NIL); - } + Printv(f_shadow, tab4, "thisown = property(lambda x: x.this.own(), ", "lambda x, v: x.this.own(v), doc=\"The membership flag\")\n", NIL); + /* Add static attribute */ + if (GetFlag(n, "feature:python:nondynamic")) { + Printv(f_shadow_file, tab4, "__setattr__ = _swig_setattr_nondynamic_instance_variable(object.__setattr__)\n", NIL); } } } @@ -4511,23 +4471,20 @@ public: SwigType *realct = Copy(real_classname); SwigType_add_pointer(realct); SwigType_remember(realct); - if (!builtin) { + if (builtin) { + Printv(f_wrappers, builtin_closures_code, NIL); + Delete(builtin_closures_code); + builtin_closures_code = NewString(""); + Clear(builtin_closures); + } else { Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL); Printv(f_wrappers, " PyObject *obj;\n", NIL); - if (modernargs) { - if (fastunpack) { - Printv(f_wrappers, " if (!SWIG_Python_UnpackTuple(args,(char *)\"swigregister\", 1, 1,&obj)) return NULL;\n", NIL); - } else { - Printv(f_wrappers, " if (!PyArg_UnpackTuple(args,(char *)\"swigregister\", 1, 1,&obj)) return NULL;\n", NIL); - } - } else { - Printv(f_wrappers, " if (!PyArg_ParseTuple(args,(char *)\"O:swigregister\", &obj)) return NULL;\n", NIL); - } + Printv(f_wrappers, " if (!SWIG_Python_UnpackTuple(args, \"swigregister\", 1, 1, &obj)) return NULL;\n", NIL); Printv(f_wrappers, " SWIG_TypeNewClientData(SWIGTYPE", SwigType_manglestr(ct), ", SWIG_NewClientData(obj));\n", " return SWIG_Py_Void();\n", "}\n\n", NIL); String *cname = NewStringf("%s_swigregister", class_name); - add_method(cname, cname, 0); + add_method(cname, cname, 0, 0, 1, 1, 1); Delete(cname); } Delete(smart); @@ -4537,7 +4494,7 @@ public: if (!builtin) Printv(f_shadow_file, "\n", tab4, "def __init__(self, *args, **kwargs):\n", tab8, "raise AttributeError(\"", "No constructor defined", (Getattr(n, "abstracts") ? " - class is abstract" : ""), "\")\n", NIL); - } else if (fastinit && !builtin) { + } else if (!builtin) { Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL); Printv(f_wrappers, " return SWIG_Python_InitShadowInstance(args);\n", "}\n\n", NIL); @@ -4548,11 +4505,7 @@ public: if (!have_repr && !builtin) { /* Supply a repr method for this class */ String *rname = SwigType_namestr(real_classname); - if (new_repr) { - Printv(f_shadow_file, tab4, "__repr__ = _swig_repr\n", NIL); - } else { - Printv(f_shadow_file, tab4, "def __repr__(self):\n", tab8, "return \"\" % (self.this,)\n", NIL); - } + Printv(f_shadow_file, tab4, "__repr__ = _swig_repr\n", NIL); Delete(rname); } @@ -4564,35 +4517,12 @@ public: builtin_tp_init = 0; } - /* Now emit methods */ - if (!builtin) - Printv(f_shadow_file, f_shadow, NIL); - - /* Now the Ptr class */ - if (classptr && !builtin) { - Printv(f_shadow_file, "\nclass ", class_name, "Ptr(", class_name, "):\n", tab4, "def __init__(self, this):\n", NIL); - if (!modern) { - Printv(f_shadow_file, - tab8, "try:\n", tab8, tab4, "self.this.append(this)\n", - tab8, "except __builtin__.Exception:\n", tab8, tab4, "self.this = this\n", tab8, "self.this.own(0)\n", tab8, "self.__class__ = ", class_name, "\n\n", NIL); - } else { - Printv(f_shadow_file, - tab8, "try:\n", tab8, tab4, "self.this.append(this)\n", - tab8, "except __builtin__.Exception:\n", tab8, tab4, "self.this = this\n", tab8, "self.this.own(0)\n", tab8, "self.__class__ = ", class_name, "\n\n", NIL); - } - } - if (!builtin) { - if (fastproxy) { - List *shadow_list = Getattr(n, "shadow_methods"); - for (int i = 0; i < Len(shadow_list); ++i) { - String *symname = Getitem(shadow_list, i); - Printf(f_shadow_file, "%s.%s = new_instancemethod(%s.%s, None, %s)\n", class_name, symname, module, Swig_name_member(NSPACE_TODO, class_name, symname), - class_name); - } - } - Printf(f_shadow_file, "%s_swigregister = %s.%s_swigregister\n", class_name, module, class_name); - Printf(f_shadow_file, "%s_swigregister(%s)\n", class_name, class_name); + /* Now emit methods */ + Printv(f_shadow_file, f_shadow, NIL); + Printf(f_shadow_file, "\n"); + Printf(f_shadow_file, "# Register %s in %s:\n", class_name, module); + Printf(f_shadow_file, "%s.%s_swigregister(%s)\n", module, class_name, class_name); } shadow_indent = 0; @@ -4606,9 +4536,6 @@ public: Clear(builtin_methods); } - classic = oldclassic; - modern = oldmodern; - /* Restore shadow file back to original version */ Delete(f_shadow); f_shadow = f_shadow_file; @@ -4662,15 +4589,19 @@ public: String *wname = Swig_name_wrapper(fullname); Setattr(class_members, symname, n); int argcount = Getattr(n, "python:argcount") ? atoi(Char(Getattr(n, "python:argcount"))) : 2; - String *ds = have_docstring(n) ? cdocstring(n, AUTODOC_FUNC) : NewString(""); + String *ds = have_docstring(n) ? cdocstring(n, AUTODOC_METHOD) : NewString(""); if (check_kwargs(n)) { - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_VARARGS|METH_KEYWORDS, (char *) \"%s\" },\n", symname, wname, ds); + // Cast via void(*)(void) to suppress GCC -Wcast-function-type + // warning. Python should always call the function correctly, but + // the Python C API requires us to store it in function pointer of a + // different type. + Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, METH_VARARGS|METH_KEYWORDS, \"%s\" },\n", symname, wname, ds); } else if (argcount == 0) { - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_NOARGS, (char *) \"%s\" },\n", symname, wname, ds); + Printf(builtin_methods, " { \"%s\", %s, METH_NOARGS, \"%s\" },\n", symname, wname, ds); } else if (argcount == 1) { - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_O, (char *) \"%s\" },\n", symname, wname, ds); + Printf(builtin_methods, " { \"%s\", %s, METH_O, \"%s\" },\n", symname, wname, ds); } else { - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_VARARGS, (char *) \"%s\" },\n", symname, wname, ds); + Printf(builtin_methods, " { \"%s\", %s, METH_VARARGS, \"%s\" },\n", symname, wname, ds); } Delete(fullname); Delete(wname); @@ -4703,6 +4634,8 @@ public: if (!have_addtofunc(n)) { if (!fastproxy || olddefs) { Printv(f_shadow, "\n", tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL); + if (have_docstring(n)) + Printv(f_shadow, tab8, docstring(n, AUTODOC_METHOD, tab8), "\n", NIL); Printv(f_shadow, tab8, "return ", funcCall(fullname, callParms), "\n", NIL); } } else { @@ -4724,13 +4657,8 @@ public: } } if (fproxy) { - List *shadow_list = Getattr(getCurrentClass(), "shadow_methods"); - if (!shadow_list) { - shadow_list = NewList(); - Setattr(getCurrentClass(), "shadow_methods", shadow_list); - Delete(shadow_list); - } - Append(shadow_list, symname); + Printf(f_shadow, tab4); + Printf(f_shadow, "%s = _swig_new_instance_method(%s.%s)\n", symname, module, Swig_name_member(NSPACE_TODO, class_name, symname)); } Delete(fullname); } @@ -4760,7 +4688,7 @@ public: String *fullname = Swig_name_member(NSPACE_TODO, class_name, symname); String *wname = Swig_name_wrapper(fullname); Setattr(class_members, symname, n); - int funpack = modernargs && fastunpack && !Getattr(n, "sym:overloaded"); + int funpack = fastunpack && !Getattr(n, "sym:overloaded"); String *pyflags = NewString("METH_STATIC|"); int argcount = Getattr(n, "python:argcount") ? atoi(Char(Getattr(n, "python:argcount"))) : 2; if (funpack && argcount == 0) @@ -4769,12 +4697,15 @@ public: Append(pyflags, "METH_O"); else Append(pyflags, "METH_VARARGS"); + // Cast via void(*)(void) to suppress GCC -Wcast-function-type warning. + // Python should always call the function correctly, but the Python C + // API requires us to store it in function pointer of a different type. if (have_docstring(n)) { String *ds = cdocstring(n, AUTODOC_STATICFUNC); - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, %s, (char *) \"%s\" },\n", symname, wname, pyflags, ds); + Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"%s\" },\n", symname, wname, pyflags, ds); Delete(ds); } else { - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, %s, \"\" },\n", symname, wname, pyflags); + Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"\" },\n", symname, wname, pyflags); } Delete(fullname); Delete(wname); @@ -4788,10 +4719,13 @@ public: } if (shadow) { - if (!Getattr(n, "feature:python:callback") && have_addtofunc(n)) { + String *staticfunc_name = NewString(fastproxy ? "_swig_new_static_method" : "staticmethod"); + bool fast = (fastproxy && !have_addtofunc(n)) || Getattr(n, "feature:callback"); + if (!fast || olddefs) { int kw = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0; String *parms = make_pyParmList(n, false, false, kw); String *callParms = make_pyParmList(n, false, true, kw); + Printv(f_shadow, "\n", tab4, "@staticmethod", NIL); Printv(f_shadow, "\n", tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL); if (have_docstring(n)) Printv(f_shadow, tab8, docstring(n, AUTODOC_STATICFUNC, tab8), "\n", NIL); @@ -4800,24 +4734,18 @@ public: if (have_pythonappend(n)) { Printv(f_shadow, tab8, "val = ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n", NIL); Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL); - Printv(f_shadow, tab8, "return val\n\n", NIL); + Printv(f_shadow, tab8, "return val\n", NIL); } else { - Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n\n", NIL); - } - Printv(f_shadow, tab4, symname, " = staticmethod(", symname, ")\n", NIL); - } else { - if (!classic) { - if (!modern) - Printv(f_shadow, tab4, "if _newclass:\n", tab4, NIL); - Printv(f_shadow, tab4, symname, " = staticmethod(", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), - ")\n", NIL); - } - if (classic || !modern) { - if (!classic) - Printv(f_shadow, tab4, "else:\n", tab4, NIL); - Printv(f_shadow, tab4, symname, " = ", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), "\n", NIL); + Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n", NIL); } } + + // Below may result in a 2nd definition of the method when -olddefs is used. The Python interpreter will use the second definition as it overwrites the first. + if (fast) { + Printv(f_shadow, tab4, symname, " = ", staticfunc_name, "(", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), + ")\n", NIL); + } + Delete(staticfunc_name); } return SWIG_OK; } @@ -4831,7 +4759,7 @@ public: int oldshadow = shadow; int use_director = Swig_directorclass(n); - /* + /* * If we're wrapping the constructor of a C++ director class, prepend a new parameter * to receive the scripting language object (e.g. 'self') * @@ -4875,11 +4803,12 @@ public: Delete(cname); } + String *subfunc = Swig_name_construct(NSPACE_TODO, symname); if (!have_constructor && handled_as_init) { if (!builtin) { if (Getattr(n, "feature:shadow")) { String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), tab4, Getfile(n), Getline(n), "%feature(\"shadow\")"); - String *pyaction = NewStringf("%s.%s", module, Swig_name_construct(NSPACE_TODO, symname)); + String *pyaction = NewStringf("%s.%s", module, subfunc); Replaceall(pycode, "$action", pyaction); Delete(pyaction); Printv(f_shadow, pycode, "\n", NIL); @@ -4893,7 +4822,7 @@ public: String *parms = make_pyParmList(n, true, false, allow_kwargs); /* Pass 'self' only if using director */ - String *callParms = make_pyParmList(n, false, true, allow_kwargs); + String *callParms = make_pyParmList(n, false, true, allow_kwargs, true); if (use_director) { Insert(callParms, 0, "_self, "); @@ -4909,13 +4838,7 @@ public: if (have_pythonprepend(n)) Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL); Printv(f_shadow, pass_self, NIL); - if (fastinit) { - Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self, ", funcCall(Swig_name_construct(NSPACE_TODO, symname), callParms), ")\n", NIL); - } else { - Printv(f_shadow, - tab8, "this = ", funcCall(Swig_name_construct(NSPACE_TODO, symname), callParms), "\n", - tab8, "try:\n", tab8, tab4, "self.this.append(this)\n", tab8, "except __builtin__.Exception:\n", tab8, tab4, "self.this = this\n", NIL); - } + Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self, ", funcCall(subfunc, callParms), ")\n", NIL); if (have_pythonappend(n)) Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n\n", NIL); Delete(pass_self); @@ -4925,39 +4848,36 @@ public: } else { /* Hmmm. We seem to be creating a different constructor. We're just going to create a function for it. */ - if (Getattr(n, "feature:shadow")) { - String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), "", Getfile(n), Getline(n), "%feature(\"shadow\")"); - String *pyaction = NewStringf("%s.%s", module, Swig_name_construct(NSPACE_TODO, symname)); - Replaceall(pycode, "$action", pyaction); - Delete(pyaction); - Printv(f_shadow_stubs, pycode, "\n", NIL); - Delete(pycode); - } else { - String *parms = make_pyParmList(n, false, false, allow_kwargs); - String *callParms = make_pyParmList(n, false, true, allow_kwargs); + if (!builtin) { + if (Getattr(n, "feature:shadow")) { + String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), "", Getfile(n), Getline(n), "%feature(\"shadow\")"); + String *pyaction = NewStringf("%s.%s", module, subfunc); + Replaceall(pycode, "$action", pyaction); + Delete(pyaction); + Printv(f_shadow_stubs, pycode, "\n", NIL); + Delete(pycode); + } else { + String *parms = make_pyParmList(n, false, false, allow_kwargs); + String *callParms = make_pyParmList(n, false, true, allow_kwargs); - Printv(f_shadow_stubs, "\ndef ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL); - if (have_docstring(n)) - Printv(f_shadow_stubs, tab4, docstring(n, AUTODOC_CTOR, tab4), "\n", NIL); - if (have_pythonprepend(n)) - Printv(f_shadow_stubs, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL); - String *subfunc = NULL; - /* - if (builtin) - subfunc = Copy(Getattr(getCurrentClass(), "sym:name")); - else - */ - subfunc = Swig_name_construct(NSPACE_TODO, symname); - Printv(f_shadow_stubs, tab4, "val = ", funcCall(subfunc, callParms), "\n", NIL); + Printv(f_shadow_stubs, "\ndef ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL); + if (have_docstring(n)) + Printv(f_shadow_stubs, tab4, docstring(n, AUTODOC_CTOR, tab4), "\n", NIL); + if (have_pythonprepend(n)) + Printv(f_shadow_stubs, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL); + Printv(f_shadow_stubs, tab4, "val = ", funcCall(subfunc, callParms), "\n", NIL); #ifdef USE_THISOWN - Printv(f_shadow_stubs, tab4, "val.thisown = 1\n", NIL); + Printv(f_shadow_stubs, tab4, "val.thisown = 1\n", NIL); #endif - if (have_pythonappend(n)) - Printv(f_shadow_stubs, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL); - Printv(f_shadow_stubs, tab4, "return val\n", NIL); - Delete(subfunc); + if (have_pythonappend(n)) + Printv(f_shadow_stubs, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL); + Printv(f_shadow_stubs, tab4, "return val\n", NIL); + } + } else { + Printf(f_shadow_stubs, "%s = %s\n", symname, subfunc); } } + Delete(subfunc); } } return SWIG_OK; @@ -4997,9 +4917,6 @@ public: } else { Printv(f_shadow, tab4, "__swig_destroy__ = ", module, ".", Swig_name_destroy(NSPACE_TODO, symname), "\n", NIL); if (!have_pythonprepend(n) && !have_pythonappend(n)) { - if (proxydel) { - Printv(f_shadow, tab4, "__del__ = lambda self: None\n", NIL); - } return SWIG_OK; } Printv(f_shadow, tab4, "def __del__(self):\n", NIL); @@ -5040,20 +4957,12 @@ public: String *setname = Swig_name_set(NSPACE_TODO, mname); String *getname = Swig_name_get(NSPACE_TODO, mname); int assignable = is_assignable(n); - if (!modern) { - if (assignable) { - Printv(f_shadow, tab4, "__swig_setmethods__[\"", symname, "\"] = ", module, ".", setname, "\n", NIL); - } - Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = ", module, ".", getname, "\n", NIL); - } - if (!classic) { - if (!modern) - Printv(f_shadow, tab4, "if _newclass:\n", tab4, NIL); - Printv(f_shadow, tab4, symname, " = _swig_property(", module, ".", getname, NIL); - if (assignable) - Printv(f_shadow, ", ", module, ".", setname, NIL); - Printv(f_shadow, ")\n", NIL); - } + Printv(f_shadow, tab4, symname, " = property(", module, ".", getname, NIL); + if (assignable) + Printv(f_shadow, ", ", module, ".", setname, NIL); + if (have_docstring(n)) + Printv(f_shadow, ", doc=", docstring(n, AUTODOC_VAR, tab4), NIL); + Printv(f_shadow, ")\n", NIL); Delete(mname); Delete(setname); Delete(getname); @@ -5099,13 +5008,13 @@ public: DelWrapper(f); int assignable = is_assignable(n); if (assignable) { - int funpack = modernargs && fastunpack; + int funpack = fastunpack; Wrapper *f = NewWrapper(); Printv(f->def, "SWIGINTERN PyObject *", wrapsetname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL); Wrapper_add_local(f, "res", "int res"); if (!funpack) { Wrapper_add_local(f, "value", "PyObject *value"); - Append(f->code, "if (!PyArg_ParseTuple(args,(char *)\"O:set\",&value)) return NULL;\n"); + Append(f->code, "if (!PyArg_ParseTuple(args, \"O:set\", &value)) return NULL;\n"); } Printf(f->code, "res = %s(%s);\n", varsetname, funpack ? "args" : "value"); Append(f->code, "return !res ? SWIG_Py_Void() : NULL;\n"); @@ -5114,18 +5023,12 @@ public: add_method(setname, wrapsetname, 0, 0, funpack, 1, 1); DelWrapper(f); } - if (!modern && !builtin) { - if (assignable) { - Printv(f_shadow, tab4, "__swig_setmethods__[\"", symname, "\"] = ", module, ".", setname, "\n", NIL); - } - Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = ", module, ".", getname, "\n", NIL); - } - if (!classic && !builtin) { - if (!modern) - Printv(f_shadow, tab4, "if _newclass:\n", tab4, NIL); - Printv(f_shadow, tab4, symname, " = _swig_property(", module, ".", getname, NIL); + if (!builtin) { + Printv(f_shadow, tab4, symname, " = property(", module, ".", getname, NIL); if (assignable) Printv(f_shadow, ", ", module, ".", setname, NIL); + if (have_docstring(n)) + Printv(f_shadow, ", doc=", docstring(n, AUTODOC_VAR, tab4), NIL); Printv(f_shadow, ")\n", NIL); } String *getter = Getattr(n, "pybuiltin:getter"); @@ -5177,13 +5080,15 @@ public: Swig_restore(n); } else if (shadow) { Printv(f_shadow, tab4, symname, " = ", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), "\n", NIL); + if (have_docstring(n)) + Printv(f_shadow, tab4, docstring(n, AUTODOC_CONST, tab4), "\n", NIL); } return SWIG_OK; } /* ------------------------------------------------------------ * insertDirective() - * + * * Hook for %insert directive. We're going to look for special %shadow inserts * as a special case so we can do indenting correctly * ------------------------------------------------------------ */ @@ -5199,9 +5104,11 @@ public: Delete(pycode); } } else if (!ImportMode && (Cmp(section, "pythonbegin") == 0)) { - String *pycode = indent_pythoncode(code, "", Getfile(n), Getline(n), "%pythonbegin or %insert(\"pythonbegin\") block"); - Printv(f_shadow_begin, pycode, NIL); - Delete(pycode); + if (shadow) { + String *pycode = indent_pythoncode(code, "", Getfile(n), Getline(n), "%pythonbegin or %insert(\"pythonbegin\") block"); + Printv(f_shadow_begin, pycode, NIL); + Delete(pycode); + } } else { Language::insertDirective(n); } @@ -5264,7 +5171,7 @@ public: /* --------------------------------------------------------------- * classDirectorMethod() * - * Emit a virtual director method to pass a method call on to the + * Emit a virtual director method to pass a method call on to the * underlying Python object. * * ** Moved it here due to internal error on gcc-2.96 ** @@ -5321,18 +5228,21 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { String *pclassname = NewStringf("SwigDirector_%s", classname); String *qualified_name = NewStringf("%s::%s", pclassname, name); SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); - target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); + target = Swig_method_decl(rtype, decl, qualified_name, l, 0); Printf(w->def, "%s", target); Delete(qualified_name); Delete(target); /* header declaration */ - target = Swig_method_decl(rtype, decl, name, l, 0, 1); + target = Swig_method_decl(rtype, decl, name, l, 1); Printf(declaration, " virtual %s", target); Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; - if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { Parm *p; int gencomma = 0; @@ -5362,12 +5272,20 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { Append(w->def, " {"); Append(declaration, ";\n"); - /* declare method return value + /* declare method return value * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { String *cres = SwigType_lstr(returntype, "c_result"); Printf(w->code, "%s;\n", cres); Delete(cres); @@ -5399,7 +5317,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { /* remove the wrapper 'w' since it was producing spurious temps */ Swig_typemap_attach_parms("in", l, 0); - Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorin", l, w); Swig_typemap_attach_parms("directorargout", l, w); Parm *p; @@ -5514,7 +5432,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { } else { Wrapper_add_localv(w, source, "swig::SwigVar_PyObject", source, "= 0", NIL); Printf(wrap_args, "%s = SWIG_InternalNewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle); - //Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n", + //Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n", // source, nonconst, base); Printv(arglist, source, NIL); } @@ -5560,34 +5478,26 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { Append(w->code, "PyObject *method = swig_get_method(swig_method_index, swig_method_name);\n"); if (Len(parse_args) > 0) { - if (use_parse || !modernargs) { + if (use_parse) { Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallFunction(method, (char *)\"(%s)\" %s);\n", Swig_cresult_name(), parse_args, arglist); } else { Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallFunctionObjArgs(method %s, NULL);\n", Swig_cresult_name(), arglist); } } else { - if (modernargs) { - Append(w->code, "swig::SwigVar_PyObject args = PyTuple_New(0);\n"); - Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_Call(method, (PyObject *) args, NULL);\n", Swig_cresult_name()); - } else { - Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallFunction(method, NULL, NULL);\n", Swig_cresult_name()); - } + Append(w->code, "swig::SwigVar_PyObject args = PyTuple_New(0);\n"); + Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_Call(method, (PyObject *) args, NULL);\n", Swig_cresult_name()); } Append(w->code, "#else\n"); if (Len(parse_args) > 0) { - if (use_parse || !modernargs) { + if (use_parse) { Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethod(swig_get_self(), (char *)\"%s\", (char *)\"(%s)\" %s);\n", Swig_cresult_name(), pyname, parse_args, arglist); } else { - Printf(w->code, "swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar((char *)\"%s\");\n", pyname); + Printf(w->code, "swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar(\"%s\");\n", pyname); Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name %s, NULL);\n", Swig_cresult_name(), arglist); } } else { - if (!modernargs) { - Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethod(swig_get_self(), (char *) \"%s\", NULL);\n", Swig_cresult_name(), pyname); - } else { - Printf(w->code, "swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar((char *)\"%s\");\n", pyname); - Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);\n", Swig_cresult_name()); - } + Printf(w->code, "swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar(\"%s\");\n", pyname); + Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);\n", Swig_cresult_name()); } Append(w->code, "#endif\n"); @@ -5616,7 +5526,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { /* * Python method may return a simple object, or a tuple. - * for in/out aruments, we have to extract the appropriate PyObjects from the tuple, + * for in/out arguments, we have to extract the appropriate PyObjects from the tuple, * then marshal everything back to C/C++ (return value and output arguments). * */ diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 301b49f9e..bb43dad48 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -1,5 +1,6 @@ + /* ----------------------------------------------------------------------------- - * This file is part of SWIG, which is licensed as a whole under version 3 + * This file is part of SWIG, which is licensed as a whole under version 3 * (or any later version) of the GNU General Public License. Some additional * terms also apply to certain portions of SWIG. The full details of the SWIG * license and copyrights can be found in the LICENSE and COPYRIGHT files @@ -12,8 +13,7 @@ * ----------------------------------------------------------------------------- */ #include "swigmod.h" - -static const double DEFAULT_NUMBER = .0000123456712312312323; +#include "cparse.h" static String* replaceInitialDash(const String *name) { @@ -32,15 +32,15 @@ static String * getRTypeName(SwigType *t, int *outCount = NULL) { List *els = SwigType_split(t); int count = 0; int i; - - if(Strncmp(b, "struct ", 7) == 0) + + if(Strncmp(b, "struct ", 7) == 0) Replace(b, "struct ", "", DOH_REPLACE_FIRST); - + /* Printf(stdout, " %s,base = %s\n", t, b); - for(i = 0; i < Len(els); i++) + for(i = 0; i < Len(els); i++) Printf(stdout, "%d) %s, ", i, Getitem(els,i)); Printf(stdout, "\n"); */ - + for(i = 0; i < Len(els); i++) { String *el = Getitem(els, i); if(Strcmp(el, "p.") == 0 || Strncmp(el, "a(", 2) == 0) { @@ -50,96 +50,57 @@ static String * getRTypeName(SwigType *t, int *outCount = NULL) { } if(outCount) *outCount = count; - + String *tmp = NewString(""); char *retName = Char(SwigType_manglestr(t)); Insert(tmp, 0, retName); return tmp; - + /* - if(count) + if(count) return(b); - - Delete(b); - return(NewString("")); + + Delete(b); + return(NewString("")); */ } -/********************* - Tries to get the name of the R class corresponding to the given type - e.g. struct A * is ARef, struct A** is ARefRef. - Now handles arrays, i.e. struct A[2] -****************/ +/* -------------------------------------------------------------- + * Tries to get the resolved name, with options of adding + * or removing a layer of references. Take care not + * to request both + * --------------------------------------------------------------*/ -static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) { - String *tmp = NewString(""); +static String *getRClassName(String *retType, int deRef=0, int upRef=0) { SwigType *resolved = SwigType_typedef_resolve_all(retType); - char *retName = Char(SwigType_manglestr(resolved)); + int ispointer = SwigType_ispointer(resolved); + int isreference = SwigType_isreference(resolved); if (upRef) { - Printf(tmp, "_p%s", retName); - } else{ - Insert(tmp, 0, retName); + SwigType_add_pointer(resolved); } - - return tmp; -/* -#if 1 - List *l = SwigType_split(retType); - int n = Len(l); - if(!l || n == 0) { -#ifdef R_SWIG_VERBOSE - if (debugMode) - Printf(stdout, "SwigType_split return an empty list for %s\n", - retType); -#endif - return(tmp); - } - - - String *el = Getitem(l, n-1); - char *ptr = Char(el); - if(strncmp(ptr, "struct ", 7) == 0) - ptr += 7; - - Printf(tmp, "%s", ptr); - - if(addRef) { - for(int i = 0; i < n; i++) { - if(Strcmp(Getitem(l, i), "p.") == 0 || - Strncmp(Getitem(l, i), "a(", 2) == 0) - Printf(tmp, "Ref"); + if (deRef) { + if (ispointer) { + SwigType_del_pointer(resolved); } - } - -#else - char *retName = Char(SwigType_manglestr(retType)); - if(!retName) - return(tmp); - - if(addRef) { - while(retName && strlen(retName) > 1 && strncmp(retName, "_p", 2) == 0) { - retName += 2; - Printf(tmp, "Ref"); + if (isreference) { + SwigType_del_reference(resolved); } - } - if(retName[0] == '_') - retName ++; - Insert(tmp, 0, retName); -#endif - - return tmp; -*/ + } + String *tmp = NewString(""); + Insert(tmp, 0, Char(SwigType_manglestr(resolved))); + return(tmp); } -/********************* - Tries to get the name of the R class corresponding to the given type - e.g. struct A * is ARef, struct A** is ARefRef. - Now handles arrays, i.e. struct A[2] -****************/ +/* -------------------------------------------------------------- + * Tries to get the name of the R class corresponding to the given type + * e.g. struct A * is ARef, struct A** is ARefRef. + * Now handles arrays, i.e. struct A[2] + * --------------------------------------------------------------*/ + static String * getRClassNameCopyStruct(String *retType, int addRef) { String *tmp = NewString(""); - + #if 1 List *l = SwigType_split(retType); int n = Len(l); @@ -149,36 +110,36 @@ static String * getRClassNameCopyStruct(String *retType, int addRef) { #endif return(tmp); } - - + + String *el = Getitem(l, n-1); char *ptr = Char(el); if(strncmp(ptr, "struct ", 7) == 0) ptr += 7; - + Printf(tmp, "%s", ptr); - + if(addRef) { for(int i = 0; i < n; i++) { - if(Strcmp(Getitem(l, i), "p.") == 0 || + if(Strcmp(Getitem(l, i), "p.") == 0 || Strncmp(Getitem(l, i), "a(", 2) == 0) Printf(tmp, "Ref"); } } - + #else char *retName = Char(SwigType_manglestr(retType)); if(!retName) return(tmp); - + if(addRef) { - while(retName && strlen(retName) > 1 && + while(retName && strlen(retName) > 1 && strncmp(retName, "_p", 2) == 0) { retName += 2; Printf(tmp, "Ref"); } } - + if(retName[0] == '_') retName ++; Insert(tmp, 0, retName); @@ -188,19 +149,20 @@ static String * getRClassNameCopyStruct(String *retType, int addRef) { } -/********************************* - Write the elements of a list to the File*, one element per line. - If quote is true, surround the element with "element". - This takes care of inserting a tab in front of each line and also - a comma after each element, except the last one. -**********************************/ +/* ------------------------------------------------------------- + * Write the elements of a list to the File*, one element per line. + * If quote is true, surround the element with "element". + * This takes care of inserting a tab in front of each line and also + * a comma after each element, except the last one. + * --------------------------------------------------------------*/ + static void writeListByLine(List *l, File *out, bool quote = 0) { int i, n = Len(l); - for(i = 0; i < n; i++) - Printf(out, "%s%s%s%s%s\n", tab8, - quote ? "\"" :"", - Getitem(l, i), + for(i = 0; i < n; i++) + Printf(out, "%s%s%s%s%s\n", tab8, + quote ? "\"" :"", + Getitem(l, i), quote ? "\"" :"", i < n-1 ? "," : ""); } @@ -208,24 +170,24 @@ static void writeListByLine(List *l, File *out, bool quote = 0) { static const char *usage = "\ R Options (available with -r)\n\ -copystruct - Emit R code to copy C structs (on by default)\n\ - -cppcast - Enable C++ casting operators (default) \n\ -debug - Output debug\n\ -dll - Name of the DLL (without the .dll or .so suffix).\n\ - Default is the module name.\n\ + Default is the module name.\n\ -gc - Aggressive garbage collection\n\ -memoryprof - Add memory profile\n\ -namespace - Output NAMESPACE file\n\ -no-init-code - Turn off the generation of the R_init_ code\n\ - (registration information still generated)\n\ + (registration information still generated)\n\ -package - Package name for the PACKAGE argument of the R .Call()\n\ - invocations. Default is the module name.\n\ + invocations. Default is the module name.\n\ "; -/************ - Display the help for this module on the screen/console. -*************/ +/* ------------------------------------------------------------- + * Display the help for this module on the screen/console. + * --------------------------------------------------------------*/ + static void showUsage() { fputs(usage, stdout); } @@ -239,10 +201,11 @@ static bool expandTypedef(SwigType *t) { } -/***** - Determine whether we should add a .copy argument to the S function - that wraps/interfaces to the routine that returns the given type. -*****/ +/* ------------------------------------------------------------- + * Determine whether we should add a .copy argument to the S function + * that wraps/interfaces to the routine that returns the given type. + * --------------------------------------------------------------*/ + static int addCopyParameter(SwigType *type) { int ok = 0; ok = Strncmp(type, "struct ", 7) == 0 || Strncmp(type, "p.struct ", 9) == 0; @@ -254,31 +217,22 @@ static int addCopyParameter(SwigType *type) { } static void replaceRClass(String *tm, SwigType *type) { - String *tmp = getRClassName(type); - String *tmp_base = getRClassName(type, 0); - String *tmp_ref = getRClassName(type, 1, 1); + String *tmp = getRClassName(type, 0, 0); + String *tmp_base = getRClassName(type, 1, 0); + String *tmp_ref = getRClassName(type, 0, 1); Replaceall(tm, "$R_class", tmp); Replaceall(tm, "$*R_class", tmp_base); Replaceall(tm, "$&R_class", tmp_ref); Delete(tmp); Delete(tmp_base); Delete(tmp_ref); } -static double getNumber(String *value) { - double d = DEFAULT_NUMBER; - if(Char(value)) { - if(sscanf(Char(value), "%lf", &d) != 1) - return(DEFAULT_NUMBER); - } - return(d); -} - class R : public Language { public: R(); void registerClass(Node *n); void main(int argc, char *argv[]); int top(Node *n); - + void dispatchFunction(Node *n); int functionWrapper(Node *n); int constantWrapper(Node *n); @@ -286,57 +240,59 @@ public: int classDeclaration(Node *n); int enumDeclaration(Node *n); - + String *enumValue(Node *n); + virtual int enumvalueDeclaration(Node *n); int membervariableHandler(Node *n); int typedefHandler(Node *n); + static List *Swig_overload_rank(Node *n, - bool script_lang_wrapping); + bool script_lang_wrapping); int memberfunctionHandler(Node *n) { if (debugMode) - Printf(stdout, " %s %s\n", + Printf(stdout, " %s %s\n", Getattr(n, "name"), Getattr(n, "type")); member_name = Getattr(n, "sym:name"); processing_class_member_function = 1; - int status = Language::memberfunctionHandler(n); + int status = Language::memberfunctionHandler(n); processing_class_member_function = 0; return status; } - /* Grab the name of the current class being processed so that we can + /* Grab the name of the current class being processed so that we can deal with members of that class. */ int classHandler(Node *n){ - if(!ClassMemberTable) + if(!ClassMemberTable) ClassMemberTable = NewHash(); - + class_name = Getattr(n, "name"); int status = Language::classHandler(n); - + class_name = NULL; return status; } // Not used: String *runtimeCode(); - + protected: int addRegistrationRoutine(String *rname, int nargs); int outputRegistrationRoutines(File *out); - + int outputCommandLineArguments(File *out); - int generateCopyRoutines(Node *n); + int generateCopyRoutines(Node *n); int DumpCode(Node *n); - + int OutputMemberReferenceMethod(String *className, int isSet, List *el, File *out); int OutputArrayMethod(String *className, List *el, File *out); int OutputClassMemberTable(Hash *tb, File *out); int OutputClassMethodsTable(File *out); int OutputClassAccessInfo(Hash *tb, File *out); - + int defineArrayAccessors(SwigType *type); - + void addNamespaceFunction(String *name) { if(!namespaceFunctions) namespaceFunctions = NewList(); @@ -348,47 +304,49 @@ protected: namespaceMethods = NewList(); Append(namespaceMethods, name); } - + String* processType(SwigType *t, Node *n, int *nargs = NULL); String *createFunctionPointerHandler(SwigType *t, Node *n, int *nargs); int addFunctionPointerProxy(String *name, Node *n, SwigType *t, String *s_paramTypes) { /*XXX Do we need to put the t in there to get the return type later. */ - if(!functionPointerProxyTable) + if(!functionPointerProxyTable) functionPointerProxyTable = NewHash(); - + Setattr(functionPointerProxyTable, name, n); - + Setattr(SClassDefs, name, name); - Printv(s_classes, "setClass('", + Printv(s_classes, "setClass('", name, - "',\n", tab8, + "',\n", tab8, "prototype = list(parameterTypes = c(", s_paramTypes, "),\n", tab8, tab8, tab8, - "returnType = '", SwigType_manglestr(t), "'),\n", tab8, + "returnType = '", SwigType_manglestr(t), "'),\n", tab8, "contains = 'CRoutinePointer')\n\n##\n", NIL); - + return SWIG_OK; } - - void addSMethodInfo(String *name, + + void addSMethodInfo(String *name, String *argType, int nargs); - // Simple initialization such as constant strings that can be reused. - void init(); - - - void addAccessor(String *memberName, Wrapper *f, + // Simple initialization such as constant strings that can be reused. + void init(); + + + void addAccessor(String *memberName, Wrapper *f, String *name, int isSet = -1); - + static int getFunctionPointerNumArgs(Node *n, SwigType *tt); -protected: +protected: bool copyStruct; bool memoryProfile; bool aggressiveGc; // Strings into which we cumulate the generated code that is to be written //vto the files. + String *enum_values; + String *enum_def_calls; String *sfile; String *f_init; String *s_classes; @@ -400,49 +358,49 @@ protected: String *s_init; String *s_init_routine; String *s_namespace; - - // State variables that carry information across calls to functionWrapper() - // from member accessors and class declarations. + + // State variables that carry information across calls to functionWrapper() + // from member accessors and class declarations. String *opaqueClassDeclaration; int processing_variable; int processing_member_access_function; String *member_name; String *class_name; - - + + int processing_class_member_function; List *class_member_functions; List *class_member_set_functions; - + /* */ Hash *ClassMemberTable; Hash *ClassMethodsTable; Hash *SClassDefs; Hash *SMethodInfo; - - // Information about routines that are generated and to be registered with - // R for dynamic lookup. + + // Information about routines that are generated and to be registered with + // R for dynamic lookup. Hash *registrationTable; Hash *functionPointerProxyTable; - + List *namespaceFunctions; List *namespaceMethods; List *namespaceClasses; // Probably can do this from ClassMemberTable. - - - // Store a copy of the command line. - // Need only keep a string that has it formatted. + + + // Store a copy of the command line. + // Need only keep a string that has it formatted. char **Argv; int Argc; bool inCPlusMode; - + // State variables that we remember from the command line settings // potentially that govern the code we generate. String *DllName; String *Rpackage; bool noInitializationCode; bool outputNamespaceInfo; - + String *UnProtectWrapupCode; // Static members @@ -453,6 +411,8 @@ R::R() : copyStruct(false), memoryProfile(false), aggressiveGc(false), + enum_values(0), + enum_def_calls(0), sfile(0), f_init(0), s_classes(0), @@ -508,7 +468,7 @@ int R::getFunctionPointerNumArgs(Node *n, SwigType *tt) { void R::addSMethodInfo(String *name, String *argType, int nargs) { (void) argType; - + if(!SMethodInfo) SMethodInfo = NewHash(); if (debugMode) @@ -531,20 +491,21 @@ void R::addSMethodInfo(String *name, String *argType, int nargs) { Setattr(tb, "max", str); } } - -/* -Returns the name of the new routine. -*/ + +/* ---------------------------------------- + * Returns the name of the new routine. + * ------------------------------------------ */ + String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { String *funName = SwigType_manglestr(t); - + /* See if we have already processed this one. */ if(functionPointerProxyTable && Getattr(functionPointerProxyTable, funName)) return funName; - + if (debugMode) Printf(stdout, " Defining %s\n", t); - + SwigType *rettype = Copy(Getattr(n, "type")); SwigType *funcparams = SwigType_functionpointer_decompose(rettype); String *rtype = SwigType_str(rettype, 0); @@ -558,29 +519,28 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { Printf(stdout, "Type: %s\n", t); Printf(stdout, "Return type: %s\n", SwigType_base(t)); } - + bool isVoidType = Strcmp(rettype, "void") == 0; if (debugMode) Printf(stdout, "%s is void ? %s (%s)\n", funName, isVoidType ? "yes" : "no", rettype); - + Wrapper *f = NewWrapper(); - + /* Go through argument list, attach lnames for arguments */ int i = 0; Parm *p = parms; for (i = 0; p; p = nextSibling(p), ++i) { String *arg = Getattr(p, "name"); String *lname; - if (!arg && Cmp(Getattr(p, "type"), "void")) { - lname = NewStringf("s_arg%d", i+1); + lname = NewStringf("arg%d", i+1); Setattr(p, "name", lname); } else lname = arg; Setattr(p, "lname", lname); } - + Swig_typemap_attach_parms("out", parms, f); Swig_typemap_attach_parms("scoerceout", parms, f); Swig_typemap_attach_parms("scheck", parms, f); @@ -589,7 +549,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { emit_parameter_variables(parms, f); emit_return_variable(n, rettype, f); -// emit_attach_parmmaps(parms,f); + // emit_attach_parmmaps(parms,f); /* Using weird name and struct to avoid potential conflicts. */ Wrapper_add_local(f, "r_swig_cb_data", "RCallbackFunctionData *r_swig_cb_data = R_SWIG_getCallbackFunctionData()"); @@ -609,60 +569,69 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { *numArgs = nargs; if (debugMode) Printf(stdout, "Setting number of parameters to %d\n", *numArgs); - } + } String *setExprElements = NewString(""); - + String *s_paramTypes = NewString(""); for(i = 0; p; i++) { SwigType *tt = Getattr(p, "type"); SwigType *name = Getattr(p, "name"); + SwigType *swig_parm_name = NewStringf("swigarg_%s", name); String *tm = Getattr(p, "tmap:out"); - Printf(f->def, "%s %s", SwigType_str(tt, 0), name); - if(tm) { - Replaceall(tm, "$1", name); - if (SwigType_isreference(tt)) { - String *tmp = NewString(""); - Append(tmp, "*"); - Append(tmp, name); - Replaceall(tm, tmp, name); + bool isVoidParm = Strcmp(tt, "void") == 0; + if (isVoidParm) + Printf(f->def, "%s", SwigType_str(tt, 0)); + else + Printf(f->def, "%s %s", SwigType_str(tt, 0), swig_parm_name); + if (tm) { + String *lstr = SwigType_lstr(tt, 0); + if (SwigType_isreference(tt) || SwigType_isrvalue_reference(tt)) { + Printf(f->code, "%s = (%s) &%s;\n", Getattr(p, "lname"), lstr, swig_parm_name); + } else if (!isVoidParm) { + Printf(f->code, "%s = (%s) %s;\n", Getattr(p, "lname"), lstr, swig_parm_name); } + Replaceall(tm, "$1", name); Replaceall(tm, "$result", "r_tmp"); + if (debugMode) { + Printf(stdout, "Calling Replace A: %s\n", Getattr(p,"type")); + } replaceRClass(tm, Getattr(p,"type")); - Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); + Replaceall(tm,"$owner", "0"); + Delete(lstr); } Printf(setExprElements, "%s\n", tm); Printf(setExprElements, "SETCAR(r_swig_cb_data->el, %s);\n", "r_tmp"); Printf(setExprElements, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n"); - + Printf(s_paramTypes, "'%s'", SwigType_manglestr(tt)); - - + + p = nextSibling(p); if(p) { Printf(f->def, ", "); Printf(s_paramTypes, ", "); } } - + Printf(f->def, ") {\n"); - + Printf(f->code, "Rf_protect(%s->expr = Rf_allocVector(LANGSXP, %d));\n", lvar, nargs + 1); Printf(f->code, "r_nprotect++;\n"); Printf(f->code, "r_swig_cb_data->el = r_swig_cb_data->expr;\n\n"); - + Printf(f->code, "SETCAR(r_swig_cb_data->el, r_swig_cb_data->fun);\n"); Printf(f->code, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n"); - + Printf(f->code, "%s\n\n", setExprElements); - - Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(", + + Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(", "r_swig_cb_data->expr,", " R_GlobalEnv,", " &r_swig_cb_data->errorOccurred", - ");\n", + ");\n", NIL); - + Printv(f->code, "\n", "if(r_swig_cb_data->errorOccurred) {\n", "R_SWIG_popCallbackFunctionData(1);\n", @@ -671,11 +640,11 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { ")\");\n", "}\n", NIL); - - - + + + if(!isVoidType) { - /* Need to deal with the return type of the function pointer, not the function pointer itself. + /* Need to deal with the return type of the function pointer, not the function pointer itself. So build a new node that has the relevant pieces. XXX Have to be a little more clever so that we can deal with struct A * - the * is getting lost. Is this still true? If so, will a SwigType_push() solve things? @@ -687,54 +656,57 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { Replaceall(tm,"$input", "r_swig_cb_data->retValue"); Replaceall(tm,"$target", Swig_cresult_name()); replaceRClass(tm, rettype); - Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); + Replaceall(tm,"$owner", "0"); Replaceall(tm,"$disown","0"); Printf(f->code, "%s\n", tm); } Delete(bbase); } - + Printv(f->code, "R_SWIG_popCallbackFunctionData(1);\n", NIL); Printv(f->code, "\n", UnProtectWrapupCode, NIL); - if (SwigType_isreference(rettype)) { + if (SwigType_isreference(rettype)) { Printv(f->code, "return *", Swig_cresult_name(), ";\n", NIL); - } else if(!isVoidType) + } else if (SwigType_isrvalue_reference(rettype)) { + Printv(f->code, "return std::move(*", Swig_cresult_name(), ");\n", NIL); + } else if (!isVoidType) { Printv(f->code, "return ", Swig_cresult_name(), ";\n", NIL); - + } + Printv(f->code, "\n}\n", NIL); Replaceall(f->code, "SWIG_exception_fail", "SWIG_exception_noreturn"); - + /* To coerce correctly in S, we really want to have an extra/intermediate - function that handles the scoerceout. + function that handles the scoerceout. We need to check if any of the argument types have an entry in that map. If none do, the ignore and call the function straight. - Otherwise, generate the a marshalling function. + Otherwise, generate a marshalling function. Need to be able to find it in S. Or use an entirely generic one that evaluates the expressions. Handle errors in the evaluation of the function by restoring - the stack, if there is one in use for this function (i.e. no + the stack, if there is one in use for this function (i.e. no userData). */ - + Wrapper_print(f, f_wrapper); - + addFunctionPointerProxy(funName, n, t, s_paramTypes); Delete(s_paramTypes); Delete(rtype); Delete(rettype); Delete(funcparams); DelWrapper(f); - + return funName; } void R::init() { - UnProtectWrapupCode = + UnProtectWrapupCode = NewStringf("%s", "vmaxset(r_vmax);\nif(r_nprotect) Rf_unprotect(r_nprotect);\n\n"); - + SClassDefs = NewHash(); - + sfile = NewString(""); f_init = NewString(""); s_header = NewString(""); @@ -744,6 +716,7 @@ void R::init() { s_classes = NewString(""); s_init = NewString(""); s_init_routine = NewString(""); + enum_def_calls = NewString(""); } @@ -759,15 +732,20 @@ int R::cDeclaration(Node *n) { #endif -/** - Method from Language that is called to start the entire - processing off, i.e. the generation of the code. - It is called after the input has been read and parsed. - Here we open the output streams and generate the code. -***/ +/* ------------------------------------------------------------- + * Method from Language that is called to start the entire + * processing off, i.e. the generation of the code. + * It is called after the input has been read and parsed. + * Here we open the output streams and generate the code. + * ------------------------------------------------------------- */ int R::top(Node *n) { String *module = Getattr(n, "name"); - if(!Rpackage) + + if (debugMode) { + Printf(stdout, " %s\n", module); + } + + if(!Rpackage) Rpackage = Copy(module); if(!DllName) DllName = Copy(module); @@ -795,7 +773,7 @@ int R::top(Node *n) { Printf(f_runtime, "\n\n#ifndef SWIGR\n#define SWIGR\n#endif\n\n"); - + Swig_banner_target_lang(s_init, "#"); outputCommandLineArguments(s_init); @@ -841,32 +819,33 @@ int R::top(Node *n) { } -/***************************************************** - Write the generated code to the .S and the .c files. -****************************************************/ +/* ------------------------------------------------------------- + * Write the generated code to the .S and the .c files. + * ------------------------------------------------------------- */ int R::DumpCode(Node *n) { String *output_filename = NewString(""); - - + + /* The name of the file in which we will generate the S code. */ Printf(output_filename, "%s%s.R", SWIG_output_directory(), Rpackage); - + #ifdef R_SWIG_VERBOSE Printf(stdout, "Writing S code to %s\n", output_filename); #endif - + File *scode = NewFile(output_filename, "w", SWIG_output_files()); if (!scode) { FileErrorDisplay(output_filename); SWIG_exit(EXIT_FAILURE); } Delete(output_filename); - - + + Printf(scode, "%s\n\n", s_init); Printf(scode, "%s\n\n", s_classes); Printf(scode, "%s\n", sfile); - + Printf(scode, "%s\n", enum_def_calls); + Delete(scode); String *outfile = Getattr(n,"outfile"); File *runtime = NewFile(outfile,"w", SWIG_output_files()); @@ -874,7 +853,7 @@ int R::DumpCode(Node *n) { FileErrorDisplay(outfile); SWIG_exit(EXIT_FAILURE); } - + Printf(runtime, "%s", f_begin); Printf(runtime, "%s\n", f_runtime); Printf(runtime, "%s\n", s_header); @@ -892,14 +871,14 @@ int R::DumpCode(Node *n) { SWIG_exit(EXIT_FAILURE); } Delete(output_filename); - + Printf(ns, "%s\n", s_namespace); Printf(ns, "\nexport(\n"); writeListByLine(namespaceFunctions, ns); Printf(ns, ")\n"); Printf(ns, "\nexportMethods(\n"); - writeListByLine(namespaceFunctions, ns, 1); + writeListByLine(namespaceMethods, ns, 1); Printf(ns, ")\n"); Delete(ns); Delete(s_namespace); @@ -910,28 +889,29 @@ int R::DumpCode(Node *n) { -/* - We may need to do more.... so this is left as a - stub for the moment. -*/ +/* ------------------------------------------------------------- + * We may need to do more.... so this is left as a + * stub for the moment. + * -------------------------------------------------------------*/ int R::OutputClassAccessInfo(Hash *tb, File *out) { int n = OutputClassMemberTable(tb, out); OutputClassMethodsTable(out); return n; } -/************************************************************************ - Currently this just writes the information collected about the - different methods of the C++ classes that have been processed - to the console. - This will be used later to define S4 generics and methods. -**************************************************************************/ +/* ------------------------------------------------------------- + * Currently this just writes the information collected about the + * different methods of the C++ classes that have been processed + * to the console. + * This will be used later to define S4 generics and methods. + * --------------------------------------------------------------*/ + int R::OutputClassMethodsTable(File *) { Hash *tb = ClassMethodsTable; - + if(!tb) return SWIG_OK; - + List *keys = Keys(tb); String *key; int i, n = Len(keys); @@ -954,75 +934,84 @@ int R::OutputClassMethodsTable(File *) { } -/* - Iterate over the _set and <>_get - elements and generate the $ and $<- functions - that provide constrained access to the member - fields in these elements. +/* -------------------------------------------------------------- + * Iterate over the _set and <>_get + * elements and generate the $ and $<- functions + * that provide constrained access to the member + * fields in these elements. + + * tb - a hash table that is built up in functionWrapper + * as we process each membervalueHandler. + * The entries are indexed by _set and + * _get. Each entry is a List *. + + * out - the stram where the code is to be written. This is the S + * code stream as we generate only S code here. + * --------------------------------------------------------------*/ - tb - a hash table that is built up in functionWrapper - as we process each membervalueHandler. - The entries are indexed by _set and - _get. Each entry is a List *. - - out - the stram where the code is to be written. This is the S - code stream as we generate only S code here.. -*/ int R::OutputClassMemberTable(Hash *tb, File *out) { List *keys = Keys(tb), *el; - + String *key; int i, n = Len(keys); /* Loop over all the _set and _get entries in the table. */ - + /* This function checks for names ending in _set - perhaps it should */ + /* use attributes of some other form, as it potentially clashes with */ + /* methods ending in _set */ + if(n && outputNamespaceInfo) { Printf(s_namespace, "exportClasses("); } for(i = 0; i < n; i++) { key = Getitem(keys, i); el = Getattr(tb, key); - + String *className = Getitem(el, 0); char *ptr = Char(key); - ptr = &ptr[Len(key) - 3]; - int isSet = strcmp(ptr, "set") == 0; - - // OutputArrayMethod(className, el, out); + int klen = Len(key); + int isSet = 0; + if (klen > 4) { + ptr = &ptr[klen - 4]; + isSet = strcmp(ptr, "_set") == 0; + } + + // OutputArrayMethod(className, el, out); OutputMemberReferenceMethod(className, isSet, el, out); - - if(outputNamespaceInfo) + + if(outputNamespaceInfo) Printf(s_namespace, "\"%s\"%s", className, i < n-1 ? "," : ""); } - if(n && outputNamespaceInfo) { + if(n && outputNamespaceInfo) { Printf(s_namespace, ")\n"); } - + return n; } -/******************************************************************* - Write the methods for $ or $<- for accessing a member field in an - struct or union (or class). - className - the name of the struct or union (e.g. Bar for struct Bar) - isSet - a logical value indicating whether the method is for - modifying ($<-) or accessing ($) the member field. - el - a list of length 2 * # accessible member elements + 1. - The first element is the name of the class. - The other pairs are member name and the name of the R function to access it. - out - the stream where we write the code. -********************************************************************/ -int R::OutputMemberReferenceMethod(String *className, int isSet, +/* -------------------------------------------------------------- + * Write the methods for $ or $<- for accessing a member field in an + * struct or union (or class). + * className - the name of the struct or union (e.g. Bar for struct Bar) + * isSet - a logical value indicating whether the method is for + * modifying ($<-) or accessing ($) the member field. + * el - a list of length 2 * # accessible member elements + 1. + * The first element is the name of the class. + * The other pairs are member name and the name of the R function to access it. + * out - the stream where we write the code. + * --------------------------------------------------------------*/ + +int R::OutputMemberReferenceMethod(String *className, int isSet, List *el, File *out) { int numMems = Len(el), j; int varaccessor = 0; - if (numMems == 0) + if (numMems == 0) return SWIG_OK; - + Wrapper *f = NewWrapper(), *attr = NewWrapper(); - + Printf(f->def, "function(x, name%s)", isSet ? ", value" : ""); Printf(attr->def, "function(x, i, j, ...%s)", isSet ? ", value" : ""); - + Printf(f->code, "{\n"); Printf(f->code, "%saccessorFuns = list(", tab8); @@ -1030,17 +1019,17 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, bool has_prev = false; for(j = 0; j < numMems; j+=3) { String *item = Getitem(el, j); - if (Getattr(itemList, item)) - continue; - Setattr(itemList, item, "1"); - String *dup = Getitem(el, j + 1); char *ptr = Char(dup); ptr = &ptr[Len(dup) - 3]; - + if (!strcmp(ptr, "get")) varaccessor++; + if (Getattr(itemList, item)) + continue; + Setattr(itemList, item, "1"); + String *pitem; if (!Strcmp(item, "operator ()")) { pitem = NewString("call"); @@ -1053,7 +1042,7 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, } else { pitem = Copy(item); } - if (has_prev) + if (has_prev) Printf(f->code, ", "); Printf(f->code, "'%s' = %s", pitem, dup); has_prev = true; @@ -1061,32 +1050,32 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, } Delete(itemList); Printf(f->code, ");\n"); - + if (!isSet && varaccessor > 0) { Printf(f->code, "%svaccessors = c(", tab8); - int vcount = 0; + int first = 1; for(j = 0; j < numMems; j+=3) { String *item = Getitem(el, j); String *dup = Getitem(el, j + 1); char *ptr = Char(dup); ptr = &ptr[Len(dup) - 3]; - + if (!strcmp(ptr, "get")) { - vcount++; - Printf(f->code, "'%s'%s", item, vcount < varaccessor ? ", " : ""); + Printf(f->code, "%s'%s'", first ? "" : ", ", item); + first = 0; } } Printf(f->code, ");\n"); } - - + + /* Printv(f->code, tab8, "idx = pmatch(name, names(accessorFuns))\n", tab8, "if(is.na(idx)) {\n", - tab8, tab4, + tab8, tab4, "stop(\"No ", (isSet ? "modifiable" : "accessible"), " field named \", name, \" in ", className, - ": fields are \", paste(names(accessorFuns), sep = \", \")", + ": fields are \", paste(names(accessorFuns), sep = \", \")", ")", "\n}\n", NIL); */ Printv(f->code, ";", tab8, "idx = pmatch(name, names(accessorFuns));\n", @@ -1108,156 +1097,227 @@ int R::OutputMemberReferenceMethod(String *className, int isSet, } } Printf(f->code, "}\n"); - - + + Printf(out, "# Start of accessor method for %s\n", className); Printf(out, "setMethod('$%s', '_p%s', ", - isSet ? "<-" : "", - getRClassName(className)); + isSet ? "<-" : "", + getRClassName(className)); Wrapper_print(f, out); Printf(out, ");\n"); - + if(isSet) { - Printf(out, "setMethod('[[<-', c('_p%s', 'character'),", - getRClassName(className)); + Printf(out, "setMethod('[[<-', c('_p%s', 'character'),", + getRClassName(className)); Insert(f->code, 2, "name = i;\n"); Printf(attr->code, "%s", f->code); Wrapper_print(attr, out); Printf(out, ");\n"); } - + DelWrapper(attr); DelWrapper(f); - + Printf(out, "# end of accessor method for %s\n", className); - + return SWIG_OK; } -/******************************************************************* - Write the methods for [ or [<- for accessing a member field in an - struct or union (or class). - className - the name of the struct or union (e.g. Bar for struct Bar) - el - a list of length 2 * # accessible member elements + 1. - The first element is the name of the class. - The other pairs are member name and the name of the R function to access it. - out - the stream where we write the code. -********************************************************************/ +/* ------------------------------------------------------------- + * Write the methods for [ or [<- for accessing a member field in an + * struct or union (or class). + * className - the name of the struct or union (e.g. Bar for struct Bar) + * el - a list of length 2 * # accessible member elements + 1. + * The first element is the name of the class. + * The other pairs are member name and the name of the R function to access it. + * out - the stream where we write the code. + * --------------------------------------------------------------*/ + int R::OutputArrayMethod(String *className, List *el, File *out) { int numMems = Len(el), j; - + if(!el || numMems == 0) return(0); - + Printf(out, "# start of array methods for %s\n", className); for(j = 0; j < numMems; j+=3) { String *item = Getitem(el, j); String *dup = Getitem(el, j + 1); if (!Strcmp(item, "__getitem__")) { - Printf(out, - "setMethod('[', '_p%s', function(x, i, j, ..., drop =TRUE) ", + Printf(out, + "setMethod('[', '_p%s', function(x, i, j, ..., drop =TRUE) ", getRClassName(className)); Printf(out, " sapply(i, function (n) %s(x, as.integer(n-1))))\n\n", dup); } if (!Strcmp(item, "__setitem__")) { - Printf(out, "setMethod('[<-', '_p%s', function(x, i, j, ..., value)", + Printf(out, "setMethod('[<-', '_p%s', function(x, i, j, ..., value)", getRClassName(className)); Printf(out, " sapply(1:length(i), function(n) %s(x, as.integer(i[n]-1), value[n])))\n\n", dup); } - + } - + Printf(out, "# end of array methods for %s\n", className); - + return SWIG_OK; } -/************************************************************ - Called when a enumeration is to be processed. - We want to call the R function defineEnumeration(). - tdname is the typedef of the enumeration, i.e. giving its name. -*************************************************************/ +/* ------------------------------------------------------------- + * Called when a enumeration is to be processed. + * We want to call the R function defineEnumeration(). + * tdname is the typedef of the enumeration, i.e. giving its name. + * --------------------------------------------------------------*/ + int R::enumDeclaration(Node *n) { - if (getCurrentClass() && (cplus_mode != PUBLIC)) - return SWIG_NOWRAP; + if (!ImportMode) { + if (getCurrentClass() && (cplus_mode != PUBLIC)) + return SWIG_NOWRAP; - String *name = Getattr(n, "name"); - String *tdname = Getattr(n, "tdname"); - - /* Using name if tdname is empty. */ - - if(Len(tdname) == 0) - tdname = name; + String *symname = Getattr(n, "sym:name"); + // TODO - deal with anonymous enumerations + // Previous enum code for R didn't wrap them + if (!symname || Getattr(n, "unnamedinstance")) + return SWIG_NOWRAP; - if(!tdname || Strcmp(tdname, "") == 0) { + // create mangled name for the enum + // This will have content if the %nspace feature is set on + // the input file + String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call + String *ename; + + String *name = Getattr(n, "name"); + ename = getRClassName(name); + if (debugMode) { + Node *current_class = getCurrentClass(); + String *cl = NewString(""); + if (current_class) { + cl = getEnumClassPrefix(); + } + Printf(stdout, "enumDeclaration: %s, %s, %s, %s, %s\n", name, symname, nspace, ename, cl); + } + Delete(name); + // set up a call to create the R enum structure. The list of + // individual elements will be built in enum_code + enum_values = 0; + // Emit each enum item Language::enumDeclaration(n); - return SWIG_OK; + + Printf(enum_def_calls, "defineEnumeration(\"%s\",\n .values=c(%s))\n\n", ename, enum_values); + Delete(enum_values); + Delete(ename); + //Delete(symname); } + return SWIG_OK; +} + +/* ------------------------------------------------------------- +* --------------------------------------------------------------*/ + +int R::enumvalueDeclaration(Node *n) { + if (getCurrentClass() && (cplus_mode != PUBLIC)) { + Printf(stdout, "evd: Not public\n"); + return SWIG_NOWRAP; + } + + Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL); + String *symname = Getattr(n, "sym:name"); + String *value = Getattr(n, "value"); + String *name = Getattr(n, "name"); + Node *parent = parentNode(n); + String *parent_name = Getattr(parent, "name"); + String *newsymname = 0; + String *tmpValue; + + // Strange hack from parent method + if (value) + tmpValue = NewString(value); + else + tmpValue = NewString(name); + // Note that this is used in enumValue() amongst other places + Setattr(n, "value", tmpValue); - String *mangled_tdname = SwigType_manglestr(tdname); - String *scode = NewString(""); - - Printv(scode, "defineEnumeration('", mangled_tdname, "'", - ",\n", tab8, tab8, tab4, ".values = c(\n", NIL); - - Node *c; - int value = -1; // First number is zero - for (c = firstChild(n); c; c = nextSibling(c)) { - // const char *tag = Char(nodeType(c)); - // if (Strcmp(tag,"cdecl") == 0) { - name = Getattr(c, "name"); - String *val = Getattr(c, "enumvalue"); - if(val && Char(val)) { - int inval = (int) getNumber(val); - if(inval == DEFAULT_NUMBER) - value++; - else - value = inval; - } else - value++; + // Deal with enum values that are not int + int swigtype = SwigType_type(Getattr(n, "type")); + if (swigtype == T_BOOL) { + const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0"; + Setattr(n, "enumvalue", val); + } else if (swigtype == T_CHAR) { + String *val = NewStringf("'%s'", Getattr(n, "enumvalue")); + Setattr(n, "enumvalue", val); + Delete(val); + } + + if (GetFlag(parent, "scopedenum")) { + newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname); + symname = newsymname; + } + + { + // Wrap C/C++ enums with constant integers or use the typesafe enum pattern + SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum "); + if (debugMode) { + Printf(stdout, "Setting type: %s\n", Copy(typemap_lookup_type)); + } + Setattr(n, "type", typemap_lookup_type); - Printf(scode, "%s%s%s'%s' = %d%s\n", tab8, tab8, tab8, name, value, - nextSibling(c) ? ", " : ""); - // } + // Simple integer constants + // Note these are always generated for anonymous enums, no matter what enum_feature is specified + // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later + + String *value = enumValue(n); + if (enum_values) { + Printf(enum_values, ",\n\"%s\" = %s", name, value); + } else { + enum_values = NewString(""); + Printf(enum_values, "\"%s\" = %s", name, value); + } + + Delete(value); } - - Printv(scode, "))", NIL); - Printf(sfile, "%s\n", scode); - - Delete(scode); - Delete(mangled_tdname); - + return SWIG_OK; } -/************************************************************* -**************************************************************/ +/* ------------------------------------------------------------- + * Create accessor functions for variables. + * Does not create equivalent wrappers for enumerations, + * which are handled differently + * --------------------------------------------------------------*/ + int R::variableWrapper(Node *n) { String *name = Getattr(n, "sym:name"); - + if (debugMode) { + Printf(stdout, "variableWrapper %s\n", n); + } processing_variable = 1; Language::variableWrapper(n); // Force the emission of the _set and _get function wrappers. processing_variable = 0; - - + + SwigType *ty = Getattr(n, "type"); + String *nodeType = nodeType(n); int addCopyParam = addCopyParameter(ty); - + //XXX processType(ty, n); - - if(!SwigType_isconst(ty)) { + + if (nodeType && !Strcmp(nodeType, "enumitem")) { + /* special wrapper for enums - don't want the R _set, _get functions*/ + if (debugMode) { + Printf(stdout, "variableWrapper enum branch\n"); + } + } else if(!SwigType_isconst(ty)) { Wrapper *f = NewWrapper(); - Printf(f->def, "%s = \nfunction(value%s)\n{\n", + Printf(f->def, "%s = \nfunction(value%s)\n{\n", name, addCopyParam ? ", .copy = FALSE" : ""); - Printv(f->code, "if(missing(value)) {\n", + Printv(f->code, "if(missing(value)) {\n", name, "_get(", addCopyParam ? ".copy" : "", ")\n}", NIL); - Printv(f->code, " else {\n", + Printv(f->code, " else {\n", name, "_set(value)\n}\n}", NIL); - + Wrapper_print(f, sfile); DelWrapper(f); } else { @@ -1267,17 +1327,25 @@ int R::variableWrapper(Node *n) { return SWIG_OK; } +/* ------------------------------------------------------------- + * Creates accessor functions for class members. -void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, + * ToDo - this version depends on naming conventions and needs + * to be replaced. + * --------------------------------------------------------------*/ + +void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, int isSet) { if(isSet < 0) { int n = Len(name); char *ptr = Char(name); - isSet = Strcmp(NewString(&ptr[n-3]), "set") == 0; + if (n>4) { + isSet = Strcmp(NewString(&ptr[n-4]), "_set") == 0; + } } - + List *l = isSet ? class_member_set_functions : class_member_functions; - + if(!l) { l = NewList(); if(isSet) @@ -1285,10 +1353,10 @@ void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, else class_member_functions = l; } - + Append(l, memberName); Append(l, name); - + String *tmp = NewString(""); Wrapper_print(wrapper, tmp); Append(l, tmp); @@ -1307,8 +1375,8 @@ struct Overloaded { }; -List * R::Swig_overload_rank(Node *n, - bool script_lang_wrapping) { +List * R::Swig_overload_rank(Node *n, + bool script_lang_wrapping) { Overloaded nodes[MAX_OVERLOAD]; int nnodes = 0; Node *o = Getattr(n,"sym:overloaded"); @@ -1339,7 +1407,7 @@ List * R::Swig_overload_rank(Node *n, } c = Getattr(c,"sym:nextSibling"); } - + /* Sort the declarations by required argument count */ { int i,j; @@ -1426,7 +1494,7 @@ List * R::Swig_overload_rank(Node *n, } /* Need subtype check here. If t2 is a subtype of t1, then we need to change the - order */ + order */ if (SwigType_issubtype(t2,t1)) { Overloaded t = nodes[i]; @@ -1542,7 +1610,7 @@ List * R::Swig_overload_rank(Node *n, int i; for (i = 0; i < nnodes; i++) { if (nodes[i].error) - Setattr(nodes[i].n, "overload:ignore", "1"); + Setattr(nodes[i].n, "overload:ignore", "1"); Append(result,nodes[i].n); // Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms)); // Swig_print_node(nodes[i].n); @@ -1555,7 +1623,7 @@ void R::dispatchFunction(Node *n) { Wrapper *f = NewWrapper(); String *symname = Getattr(n, "sym:name"); String *nodeType = Getattr(n, "nodeType"); - bool constructor = (!Cmp(nodeType, "constructor")); + bool constructor = (!Cmp(nodeType, "constructor")); String *sfname = NewString(symname); @@ -1569,7 +1637,7 @@ void R::dispatchFunction(Node *n) { } List *dispatch = Swig_overload_rank(n, true); int nfunc = Len(dispatch); - Printv(f->code, + Printv(f->code, "argtypes <- mapply(class, list(...));\n", "argv <- list(...);\n", "argc <- length(argtypes);\n", NIL ); @@ -1582,7 +1650,7 @@ void R::dispatchFunction(Node *n) { Parm *pi = Getattr(ni,"wrap:parms"); int num_arguments = emit_num_arguments(pi); - String *overname = Getattr(ni,"sym:overname"); + String *overname = Getattr(ni,"sym:overname"); if (cur_args != num_arguments) { if (cur_args != -1) { Printv(f->code, "} else ", NIL); @@ -1623,37 +1691,29 @@ void R::dispatchFunction(Node *n) { Printf(stdout, "%s\n", tmcheck); } Printf(f->code, "%s(%s)", - j == 0? "" : " && ", + j == 0 ? "" : " && ", tmcheck); p = Getattr(p, "tmap:in:next"); continue; } + // Below should be migrated into rtypecheck typemaps if (tm) { - if (Strcmp(tm,"numeric")==0) { - Printf(f->code, "%sis.numeric(argv[[%d]])", - j == 0 ? "" : " && ", - j+1); - } - else if (Strcmp(tm,"integer")==0) { - Printf(f->code, "%s(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))", - j == 0 ? "" : " && ", - j+1, j+1); - } - else if (Strcmp(tm,"character")==0) { - Printf(f->code, "%sis.character(argv[[%d]])", - j == 0 ? "" : " && ", - j+1); - } - else { - Printf(f->code, "%sextends(argtypes[%d], '%s')", - j == 0 ? "" : " && ", - j+1, - tm); + Printf(f->code, "%s", j == 0 ? "" : " && "); + if (Strcmp(tm, "numeric") == 0) { + Printf(f->code, "is.numeric(argv[[%d]])", j+1); + } else if (Strcmp(tm, "integer") == 0) { + Printf(f->code, "(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))", j+1, j+1); + } else if (Strcmp(tm, "character") == 0) { + Printf(f->code, "is.character(argv[[%d]])", j+1); + } else { + if (SwigType_ispointer(Getattr(p, "type"))) + Printf(f->code, "(extends(argtypes[%d], '%s') || is.null(argv[[%d]]))", j+1, tm, j+1); + else + Printf(f->code, "extends(argtypes[%d], '%s')", j+1, tm); } } if (!SwigType_ispointer(Getattr(p, "type"))) { - Printf(f->code, " && length(argv[[%d]]) == 1", - j+1); + Printf(f->code, " && length(argv[[%d]]) == 1", j+1); } p = Getattr(p, "tmap:in:next"); } @@ -1675,90 +1735,95 @@ void R::dispatchFunction(Node *n) { DelWrapper(f); } -/****************************************************************** +/*-------------------------------------------------------------- + +* --------------------------------------------------------------*/ -*******************************************************************/ int R::functionWrapper(Node *n) { String *fname = Getattr(n, "name"); String *iname = Getattr(n, "sym:name"); - String *type = Getattr(n, "type"); - + String *type = Getattr(n, "type"); + if (debugMode) { - Printf(stdout, + Printf(stdout, " %s %s %s\n", fname, iname, type); } String *overname = 0; String *nodeType = Getattr(n, "nodeType"); - bool constructor = (!Cmp(nodeType, "constructor")); - bool destructor = (!Cmp(nodeType, "destructor")); - + bool constructor = (!Cmp(nodeType, "constructor")); + bool destructor = (!Cmp(nodeType, "destructor")); + String *sfname = NewString(iname); - + if (constructor) Replace(sfname, "new_", "", DOH_REPLACE_FIRST); - + if (Getattr(n,"sym:overloaded")) { - overname = Getattr(n,"sym:overname"); + overname = Getattr(n,"sym:overname"); Append(sfname, overname); } - - if (debugMode) - Printf(stdout, + + if (debugMode) + Printf(stdout, " processing parameters\n"); - - + + ParmList *l = Getattr(n, "parms"); Parm *p; String *tm; - + p = l; while(p) { SwigType *resultType = Getattr(p, "type"); - if (expandTypedef(resultType) && + if (expandTypedef(resultType) && SwigType_istypedef(resultType)) { SwigType *resolved = SwigType_typedef_resolve_all(resultType); if (expandTypedef(resolved)) { + if (debugMode) { + Printf(stdout, "Setting type: %s\n", resolved); + } Setattr(p, "type", Copy(resolved)); } } p = nextSibling(p); - } + } - String *unresolved_return_type = + String *unresolved_return_type = Copy(type); if (expandTypedef(type) && SwigType_istypedef(type)) { - SwigType *resolved = + SwigType *resolved = SwigType_typedef_resolve_all(type); + if (debugMode) + Printf(stdout, " resolved %s\n", Copy(unresolved_return_type)); if (expandTypedef(resolved)) { type = Copy(resolved); Setattr(n, "type", type); } } - if (debugMode) - Printf(stdout, " unresolved_return_type %s\n", - unresolved_return_type); + if (debugMode) + Printf(stdout, " unresolved_return_type %s\n", unresolved_return_type); if(processing_member_access_function) { if (debugMode) - Printf(stdout, " '%s' '%s' '%s' '%s'\n", - fname, iname, member_name, class_name); - + Printf(stdout, " '%s' '%s' '%s' '%s'\n", fname, iname, member_name, class_name); + if(opaqueClassDeclaration) return SWIG_OK; - - - /* Add the name of this member to a list for this class_name. + + + /* Add the name of this member to a list for this class_name. We will dump all these at the end. */ - + int n = Len(iname); char *ptr = Char(iname); - bool isSet(Strcmp(NewString(&ptr[n-3]), "set") == 0); - - + bool isSet(0); + if (n > 4) isSet = Strcmp(NewString(&ptr[n-4]), "_set") == 0; + + String *tmp = NewString(""); Printf(tmp, "%s_%s", class_name, isSet ? "set" : "get"); - + List *memList = Getattr(ClassMemberTable, tmp); if(!memList) { memList = NewList(); @@ -1769,29 +1834,29 @@ int R::functionWrapper(Node *n) { Append(memList, member_name); Append(memList, iname); } - + int i; int nargs; - + String *wname = Swig_name_wrapper(iname); Replace(wname, "_wrap", "R_swig", DOH_REPLACE_FIRST); - if(overname) + if(overname) Append(wname, overname); Setattr(n,"wrap:name", wname); Wrapper *f = NewWrapper(); Wrapper *sfun = NewWrapper(); - + int isVoidReturnType = (Strcmp(type, "void") == 0); - // Need to use the unresolved return type since - // typedef resolution removes the const which causes a + // Need to use the unresolved return type since + // typedef resolution removes the const which causes a // mismatch with the function action emit_return_variable(n, unresolved_return_type, f); SwigType *rtype = Getattr(n, "type"); int addCopyParam = 0; - if(!isVoidReturnType) + if(!isVoidReturnType) addCopyParam = addCopyParameter(rtype); @@ -1800,16 +1865,24 @@ int R::functionWrapper(Node *n) { // if(addCopyParam) if (debugMode) - Printf(stdout, "Adding a .copy argument to %s for %s = %s\n", + Printf(stdout, "Adding a .copy argument to %s for %s = %s\n", iname, type, addCopyParam ? "yes" : "no"); Printv(f->def, "SWIGEXPORT SEXP\n", wname, " ( ", NIL); - Printf(sfun->def, "# Start of %s\n", iname); + Printf(sfun->def, "# Start of %s\n", iname); Printv(sfun->def, "\n`", sfname, "` = function(", NIL); - if(outputNamespaceInfo) //XXX Need to be a little more discriminating - addNamespaceFunction(iname); + if(outputNamespaceInfo) {//XXX Need to be a little more discriminating + if (constructor) { + String *niname = Copy(iname); + Replace(niname, "new_", "", DOH_REPLACE_FIRST); + addNamespaceFunction(niname); + Delete(niname); + } else { + addNamespaceFunction(iname); + } + } Swig_typemap_attach_parms("scoercein", l, f); Swig_typemap_attach_parms("scoerceout", l, f); @@ -1871,7 +1944,7 @@ int R::functionWrapper(Node *n) { name = Copy(name); Insert(name, 0, "s_"); } - + if(processing_variable) { name = Copy(name); Insert(name, 0, "s_"); @@ -1896,7 +1969,7 @@ int R::functionWrapper(Node *n) { String *snargs = NewStringf("%d", nargs); Printv(sfun->code, "if(is.function(", name, ")) {", "\n", - "assert('...' %in% names(formals(", name, + "assert('...' %in% names(formals(", name, ")) || length(formals(", name, ")) >= ", snargs, ");\n} ", NIL); Delete(snargs); @@ -1951,11 +2024,11 @@ int R::functionWrapper(Node *n) { Printf(f->code,"%s\n",tm); - if(funcptr_name) - Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n", + if(funcptr_name) + Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n", lname, funcptr_name, name); Printv(f->def, inFirstArg ? "" : ", ", "SEXP ", name, NIL); - if (Len(name) != 0) + if (Len(name) != 0) inFirstArg = false; p = Getattr(p,"tmap:in:next"); @@ -1972,7 +2045,7 @@ int R::functionWrapper(Node *n) { Printf(s_inputMap, "%s%s='%s'", inFirstType ? "" : ", ", name, tm); inFirstType = false; - if(funcptr_name) + if(funcptr_name) Delete(funcptr_name); } /* end of looping over parameters. */ @@ -2011,7 +2084,7 @@ int R::functionWrapper(Node *n) { Replaceall(tm,"$n", pos); // The position into which to store the answer. Replaceall(tm,"$arg", Getattr(p, "emit:input")); Replaceall(tm,"$input", Getattr(p, "emit:input")); - Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); + Replaceall(tm,"$owner", "0"); Printf(outargs, "%s\n", tm); @@ -2023,22 +2096,20 @@ int R::functionWrapper(Node *n) { String *actioncode = emit_action(n); /* Deal with the explicit return value. */ - if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) { + if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) { SwigType *retType = Getattr(n, "type"); - //Printf(stdout, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no"); - /* if(SwigType_isarray(retType)) { - defineArrayAccessors(retType); - } */ - - + Replaceall(tm,"$1", Swig_cresult_name()); Replaceall(tm,"$result", "r_ans"); + if (debugMode){ + Printf(stdout, "Calling replace D: %s, %s, %s\n", retType, n, tm); + } replaceRClass(tm, retType); if (GetFlag(n,"feature:new")) { - Replaceall(tm, "$owner", "R_SWIG_OWNER"); + Replaceall(tm, "$owner", "SWIG_POINTER_OWN"); } else { - Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); + Replaceall(tm,"$owner", "0"); } #if 0 @@ -2046,11 +2117,11 @@ int R::functionWrapper(Node *n) { Printf(f->code, "if(LOGICAL(s_swig_copy)[0]) {\n"); Printf(f->code, "/* Deal with returning a reference. */\nr_ans = R_NilValue;\n"); Printf(f->code, "}\n else {\n"); - } + } #endif Printf(f->code, "%s\n", tm); #if 0 - if(addCopyParam) + if(addCopyParam) Printf(f->code, "}\n"); /* end of if(s_swig_copy) ... else { ... } */ #endif @@ -2067,8 +2138,8 @@ int R::functionWrapper(Node *n) { if(!isVoidReturnType) Printf(tmp, "Rf_protect(r_ans);\n"); - Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n", - numOutArgs + !isVoidReturnType, + Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n", + numOutArgs + !isVoidReturnType, isVoidReturnType ? 1 : 2); if(!isVoidReturnType) @@ -2076,7 +2147,7 @@ int R::functionWrapper(Node *n) { Printf(tmp, "r_ans = R_OutputValues;\n"); Insert(outargs, 0, tmp); - Delete(tmp); + Delete(tmp); @@ -2097,28 +2168,47 @@ int R::functionWrapper(Node *n) { } } + /* See if there is any return cleanup code */ + if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) { + Replaceall(tm, "$source", Swig_cresult_name()); + Printf(f->code, "%s\n", tm); + Delete(tm); + } + Printv(f->code, UnProtectWrapupCode, NIL); /*If the user gave us something to convert the result in */ if ((tm = Swig_typemap_lookup("scoerceout", n, Swig_cresult_name(), sfun))) { Replaceall(tm,"$source","ans"); Replaceall(tm,"$result","ans"); + if (constructor) { + Node * parent = Getattr(n, "parentNode"); + String * smartname = Getattr(parent, "feature:smartptr"); + if (smartname) { + smartname = getRClassName(smartname, 1, 1); + Replaceall(tm, "$R_class", smartname); + Delete(smartname); + } + } + if (debugMode) { + Printf(stdout, "Calling replace B: %s, %s, %s\n", Getattr(n, "type"), Getattr(n, "sym:name"), getNSpace()); + } replaceRClass(tm, Getattr(n, "type")); Chop(tm); } - Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname, + Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname, "', ", sargs, "PACKAGE='", Rpackage, "');\n", NIL); if(Len(tm)) { - Printf(sfun->code, "%s\n\n", tm); + Printf(sfun->code, "%s\n\n", tm); if (constructor) - { + { String *finalizer = NewString(iname); Replace(finalizer, "new_", "", DOH_REPLACE_FIRST); Printf(sfun->code, "reg.finalizer(ans@ref, delete_%s)\n", finalizer); - } + } Printf(sfun->code, "ans\n"); } @@ -2138,18 +2228,21 @@ int R::functionWrapper(Node *n) { tm = Swig_typemap_lookup("rtype", n, "", 0); if(tm) { SwigType *retType = Getattr(n, "type"); + if (debugMode) { + Printf(stdout, "Calling replace C: %s\n", Copy(retType)); + } replaceRClass(tm, retType); - } - - Printv(sfile, "attr(`", sfname, "`, 'returnType') = '", - isVoidReturnType ? "void" : (tm ? tm : ""), - "'\n", NIL); - + } + + Printv(sfile, "attr(`", sfname, "`, 'returnType') = '", + isVoidReturnType ? "void" : (tm ? tm : ""), + "'\n", NIL); + if(nargs > 0) Printv(sfile, "attr(`", sfname, "`, \"inputTypes\") = c(", s_inputTypes, ")\n", NIL); - Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('", - sfname, "'))\n\n", NIL); + Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('", + sfname, "'))\n\n", NIL); if (memoryProfile) { Printv(sfile, "memory.profile()\n", NIL); @@ -2162,8 +2255,8 @@ int R::functionWrapper(Node *n) { - /* If we are dealing with a method in an C++ class, then - add the name of the R function and its definition. + /* If we are dealing with a method in an C++ class, then + add the name of the R function and its definition. XXX need to figure out how to store the Wrapper if possible in the hash/list. Would like to be able to do this so that we can potentially insert */ @@ -2196,45 +2289,47 @@ int R::constantWrapper(Node *n) { return SWIG_OK; } -/***************************************************** - Add the specified routine name to the collection of - generated routines that are called from R functions. - This is used to register the routines with R for - resolving symbols. +/*-------------------------------------------------------------- + * Add the specified routine name to the collection of + * generated routines that are called from R functions. + * This is used to register the routines with R for + * resolving symbols. + + * rname - the name of the routine + * nargs - the number of arguments it expects. + * --------------------------------------------------------------*/ - rname - the name of the routine - nargs - the number of arguments it expects. -******************************************************/ int R::addRegistrationRoutine(String *rname, int nargs) { - if(!registrationTable) + if(!registrationTable) registrationTable = NewHash(); - String *el = + String *el = NewStringf("{\"%s\", (DL_FUNC) &%s, %d}", rname, rname, nargs); - + Setattr(registrationTable, rname, el); return SWIG_OK; } -/***************************************************** - Write the registration information to an array and - create the initialization routine for registering - these. -******************************************************/ +/* ------------------------------------------------------------- + * Write the registration information to an array and + * create the initialization routine for registering + * these. + * --------------------------------------------------------------*/ + int R::outputRegistrationRoutines(File *out) { int i, n; - if(!registrationTable) + if(!registrationTable) return(0); - if(inCPlusMode) + if(inCPlusMode) Printf(out, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"); Printf(out, "#include \n\n"); - if(inCPlusMode) + if(inCPlusMode) Printf(out, "#ifdef __cplusplus\n}\n#endif\n\n"); Printf(out, "SWIGINTERN R_CallMethodDef CallEntries[] = {\n"); - + List *keys = Keys(registrationTable); n = Len(keys); for(i = 0; i < n; i++) @@ -2245,7 +2340,13 @@ int R::outputRegistrationRoutines(File *out) { if(!noInitializationCode) { if (inCPlusMode) Printv(out, "extern \"C\" ", NIL); - Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage); + { /* R allows pckage names to have '.' in the name, which is not allowed in C++ var names + we simply replace all occurrences of '.' with '_' to construct the var name */ + String * Rpackage_sane = Copy(Rpackage); + Replace(Rpackage_sane, ".", "_", DOH_REPLACE_ANY); + Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage_sane); + Delete(Rpackage_sane); + } Printf(out, "%sR_registerRoutines(dll, NULL, CallEntries, NULL, NULL);\n", tab4); if(Len(s_init_routine)) { Printf(out, "\n%s\n", s_init_routine); @@ -2258,17 +2359,17 @@ int R::outputRegistrationRoutines(File *out) { -/**************************************************************************** - Process a struct, union or class declaration in the source code, - or an anonymous typedef struct - -*****************************************************************************/ -//XXX What do we need to do here - +/* ------------------------------------------------------------- + * Process a struct, union or class declaration in the source code, + * or an anonymous typedef struct + * --------------------------------------------------------------*/ + +//XXX What do we need to do here - // Define an S4 class to refer to this. void R::registerClass(Node *n) { - String *name = Getattr(n, "name"); - String *kind = Getattr(n, "kind"); + String *name = Getattr(n, "name"); + String *kind = Getattr(n, "kind"); if (debugMode) Swig_print_node(n); @@ -2284,33 +2385,57 @@ void R::registerClass(Node *n) { Printf(base, "c("); for(int i = 0; i < Len(l); i++) { registerClass(Getitem(l, i)); - Printf(base, "'_p%s'%s", - SwigType_manglestr(Getattr(Getitem(l, i), "name")), - i < Len(l)-1 ? ", " : ""); + Printf(base, "'_p%s'%s", + SwigType_manglestr(Getattr(Getitem(l, i), "name")), + i < Len(l)-1 ? ", " : ""); } Printf(base, ")"); } else { base = NewString("'C++Reference'"); } - } else + } else base = NewString("'ExternalReference'"); Printf(s_classes, "setClass('%s', contains = %s)\n", sname, base); Delete(base); + String *smartptr = Getattr(n, "feature:smartptr"); + if (smartptr) { + List *l = Getattr(n, "bases"); + SwigType *spt = Swig_cparse_type(smartptr); + String *smart = SwigType_typedef_resolve_all(spt); + String *smart_rname = SwigType_manglestr(smart); + Printf(s_classes, "setClass('_p%s', contains = c('%s'", smart_rname, sname); + Delete(spt); + Delete(smart); + Delete(smart_rname); + for(int i = 0; i < Len(l); i++) { + Node * b = Getitem(l, i); + smartptr = Getattr(b, "feature:smartptr"); + if (smartptr) { + spt = Swig_cparse_type(smartptr); + smart = SwigType_typedef_resolve_all(spt); + smart_rname = SwigType_manglestr(smart); + Printf(s_classes, ", '_p%s'", smart_rname); + Delete(spt); + Delete(smart); + Delete(smart_rname); + } + } + Printf(s_classes, "))\n"); + } } - } int R::classDeclaration(Node *n) { - String *name = Getattr(n, "name"); - String *kind = Getattr(n, "kind"); + String *name = Getattr(n, "name"); + String *kind = Getattr(n, "kind"); if (debugMode) Swig_print_node(n); registerClass(n); - + /* If we have a typedef union { ... } U, then we never get to see the typedef via a regular call to typedefHandler. Instead, */ if(Getattr(n, "unnamed") && Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "typedef") == 0 @@ -2330,7 +2455,7 @@ int R::classDeclaration(Node *n) { opaqueClassDeclaration = NULL; - // OutputArrayMethod(name, class_member_functions, sfile); + // OutputArrayMethod(name, class_member_functions, sfile); if (class_member_functions) OutputMemberReferenceMethod(name, 0, class_member_functions, sfile); if (class_member_set_functions) @@ -2345,14 +2470,12 @@ int R::classDeclaration(Node *n) { class_member_set_functions = NULL; } if (Getattr(n, "has_destructor")) { - Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n", - getRClassName(Getattr(n, "name")), - getRClassName(Getattr(n, "name"))); + Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n", getRClassName(name), getRClassName(name)); } if(!opaque && !Strcmp(kind, "struct") && copyStruct) { - String *def = + String *def = NewStringf("setClass(\"%s\",\n%srepresentation(\n", name, tab4); bool firstItem = true; @@ -2361,7 +2484,7 @@ int R::classDeclaration(Node *n) { String *tp; elName = Getattr(c, "name"); - + String *elKind = Getattr(c, "kind"); if (!Equal(elKind, "variable")) { c = nextSibling(c); @@ -2391,12 +2514,12 @@ int R::classDeclaration(Node *n) { if (!firstItem) { Printf(def, ",\n"); - } - // else + } + // else //XXX How can we tell if this is already done. // SwigType_push(elType, elDecl); - - + + // returns "" tp = processType(elType, c, NULL); // Printf(stdout, " elType %p\n", elType); // tp = getRClassNameCopyStruct(Getattr(c, "type"), 1); @@ -2421,12 +2544,13 @@ int R::classDeclaration(Node *n) { -/*************************************************************** - Create the C routines that copy an S object of the class given - by the given struct definition in Node *n to the C value - and also the routine that goes from the C routine to an object - of this S class. -****************************************************************/ +/* ------------------------------------------------------------- + * Create the C routines that copy an S object of the class given + * by the given struct definition in Node *n to the C value + * and also the routine that goes from the C routine to an object + * of this S class. + * --------------------------------------------------------------*/ + /*XXX Clean up the toCRef - make certain the names are correct for the types, etc. in all cases. @@ -2435,7 +2559,7 @@ int R::classDeclaration(Node *n) { int R::generateCopyRoutines(Node *n) { Wrapper *copyToR = NewWrapper(); Wrapper *copyToC = NewWrapper(); - + String *name = Getattr(n, "name"); String *tdname = Getattr(n, "tdname"); String *kind = Getattr(n, "kind"); @@ -2452,9 +2576,9 @@ int R::generateCopyRoutines(Node *n) { if (debugMode) Printf(stdout, "generateCopyRoutines: name = %s, %s\n", name, type); - Printf(copyToR->def, "CopyToR%s = function(value, obj = new(\"%s\"))\n{\n", + Printf(copyToR->def, "CopyToR%s = function(value, obj = new(\"%s\"))\n{\n", mangledName, name); - Printf(copyToC->def, "CopyToC%s = function(value, obj)\n{\n", + Printf(copyToC->def, "CopyToC%s = function(value, obj)\n{\n", mangledName); Node *c = firstChild(n); @@ -2490,22 +2614,22 @@ int R::generateCopyRoutines(Node *n) { } Printf(copyToR->code, "obj;\n}\n\n"); String *rclassName = getRClassNameCopyStruct(type, 0); // without the Ref. - Printf(sfile, "# Start definition of copy functions & methods for %s\n", rclassName); - + Printf(sfile, "# Start definition of copy functions & methods for %s\n", rclassName); + Wrapper_print(copyToR, sfile); Printf(copyToC->code, "obj\n}\n\n"); Wrapper_print(copyToC, sfile); - - - Printf(sfile, "# Start definition of copy methods for %s\n", rclassName); - Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s);\n", rclassName, + + + Printf(sfile, "# Start definition of copy methods for %s\n", rclassName); + Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s);\n", rclassName, mangledName); - Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName, + Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName, mangledName); - - Printf(sfile, "# End definition of copy methods for %s\n", rclassName); - Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName); - + + Printf(sfile, "# End definition of copy methods for %s\n", rclassName); + Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName); + String *m = NewStringf("%sCopyToR", name); addNamespaceMethod(m); char *tt = Char(m); tt[Len(m)-1] = 'C'; @@ -2521,13 +2645,14 @@ int R::generateCopyRoutines(Node *n) { -/***** - Called when there is a typedef to be invoked. +/* ------------------------------------------------------------- + * Called when there is a typedef to be invoked. + * + * XXX Needs to be enhanced or split to handle the case where we have a + * typedef within a classDeclaration emission because the struct/union/etc. + * is anonymous. + * --------------------------------------------------------------*/ - XXX Needs to be enhanced or split to handle the case where we have a - typedef within a classDeclaration emission because the struct/union/etc. - is anonymous. -******/ int R::typedefHandler(Node *n) { SwigType *tp = Getattr(n, "type"); String *type = Getattr(n, "type"); @@ -2542,7 +2667,7 @@ int R::typedefHandler(Node *n) { trueName += 7; if (debugMode) Printf(stdout, " Defining S class %s\n", trueName); - Printf(s_classes, "setClass('_p%s', contains = 'ExternalReference')\n", + Printf(s_classes, "setClass('_p%s', contains = 'ExternalReference')\n", SwigType_manglestr(name)); } @@ -2551,19 +2676,20 @@ int R::typedefHandler(Node *n) { -/********************* - Called when processing a field in a "class", i.e. struct, union or - actual class. We set a state variable so that we can correctly - interpret the resulting functionWrapper() call and understand that - it is for a field element. -**********************/ +/* -------------------------------------------------------------- + * Called when processing a field in a "class", i.e. struct, union or + * actual class. We set a state variable so that we can correctly + * interpret the resulting functionWrapper() call and understand that + * it is for a field element. + * --------------------------------------------------------------*/ + int R::membervariableHandler(Node *n) { SwigType *t = Getattr(n, "type"); processType(t, n, NULL); processing_member_access_function = 1; member_name = Getattr(n,"sym:name"); if (debugMode) - Printf(stdout, " name = %s, sym:name = %s\n", + Printf(stdout, " name = %s, sym:name = %s\n", Getattr(n, "name"), member_name); int status(Language::membervariableHandler(n)); @@ -2591,14 +2717,15 @@ String * R::runtimeCode() { } -/** - Called when SWIG wants to initialize this - We initialize anythin we want here. - Most importantly, tell SWIG where to find the files (e.g. r.swg) for this module. - Use Swig_mark_arg() to tell SWIG that it is understood and not to throw an error. -**/ +/* ----------------------------------------------------------------------- + * Called when SWIG wants to initialize this + * We initialize anythin we want here. + * Most importantly, tell SWIG where to find the files (e.g. r.swg) for this module. + * Use Swig_mark_arg() to tell SWIG that it is understood and not to + * throw an error. + * --------------------------------------------------------------*/ + void R::main(int argc, char *argv[]) { - bool cppcast = true; init(); Preprocessor_define("SWIGR 1", 0); SWIG_library_directory("r"); @@ -2614,7 +2741,7 @@ void R::main(int argc, char *argv[]) { this->Argc = argc; this->Argv = argv; - allow_overloading();// can we support this? + allow_overloading();// can we support this? for(int i = 0; i < argc; i++) { if(strcmp(argv[i], "-package") == 0) { @@ -2642,12 +2769,6 @@ void R::main(int argc, char *argv[]) { } else if(!strcmp(argv[i], "-debug")) { debugMode = true; Swig_mark_arg(i); - } else if (!strcmp(argv[i],"-cppcast")) { - cppcast = true; - Swig_mark_arg(i); - } else if (!strcmp(argv[i],"-nocppcast")) { - cppcast = false; - Swig_mark_arg(i); } else if (!strcmp(argv[i],"-copystruct")) { copyStruct = true; Swig_mark_arg(i); @@ -2666,10 +2787,13 @@ void R::main(int argc, char *argv[]) { } else if (!strcmp(argv[i], "-noaggressivegc")) { aggressiveGc = false; Swig_mark_arg(i); - } - - if (cppcast) { - Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0); + } else if (strcmp(argv[i], "-cppcast") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]); + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-nocppcast") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]); + Swig_mark_arg(i); + SWIG_exit(EXIT_FAILURE); } if (debugMode) { @@ -2683,10 +2807,10 @@ void R::main(int argc, char *argv[]) { } } -/* - Could make this work for String or File and then just store the resulting string - rather than the collection of arguments and argc. -*/ +/* ----------------------------------------------------------------------- + * Could make this work for String or File and then just store the resulting string + * rather than the collection of arguments and argc. + * ----------------------------------------------------------------------- */ int R::outputCommandLineArguments(File *out) { if(Argc < 1 || !Argv || !Argv[0]) @@ -2703,32 +2827,31 @@ int R::outputCommandLineArguments(File *out) -/* How SWIG instantiates an object from this module. +/* How SWIG instantiates an object from this module. See swigmain.cxx */ -extern "C" +extern "C" Language *swig_r(void) { return new R(); } -/*************************************************************************************/ -/* - Needs to be reworked. -*/ +/* ----------------------------------------------------------------------- + * Needs to be reworked. + *----------------------------------------------------------------------- */ String * R::processType(SwigType *t, Node *n, int *nargs) { //XXX Need to handle typedefs, e.g. // a type which is a typedef to a function pointer. SwigType *tmp = Getattr(n, "tdname"); if (debugMode) - Printf(stdout, "processType %s (tdname = %s)\n", Getattr(n, "name"), tmp); - + Printf(stdout, "processType %s (tdname = %s)(SwigType = %s)\n", Getattr(n, "name"), tmp, Copy(t)); + SwigType *td = t; if (expandTypedef(t) && SwigType_istypedef(t)) { - SwigType *resolved = + SwigType *resolved = SwigType_typedef_resolve_all(t); if (expandTypedef(resolved)) { td = Copy(resolved); @@ -2742,10 +2865,10 @@ String * R::processType(SwigType *t, Node *n, int *nargs) { if (debugMode) Printf(stdout, " Defining class %s\n", b); - Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", b); + Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", b); Setattr(SClassDefs, b, b); } - + } @@ -2754,9 +2877,9 @@ String * R::processType(SwigType *t, Node *n, int *nargs) { if(SwigType_isfunctionpointer(t)) { if (debugMode) - Printf(stdout, + Printf(stdout, " Defining pointer handler %s\n", t); - + String *tmp = createFunctionPointerHandler(t, n, nargs); return tmp; } @@ -2769,16 +2892,54 @@ String * R::processType(SwigType *t, Node *n, int *nargs) { } +/* ----------------------------------------------------------------------- + * enumValue() + * This method will return a string with an enum value to use in from R when + * setting up an enum variable + * ------------------------------------------------------------------------ */ +String *R::enumValue(Node *n) { + String *symname = Getattr(n, "sym:name"); + String *value = Getattr(n, "value"); + String *newsymname = 0; + Node *parent = parentNode(n); + symname = Getattr(n, "sym:name"); + + // parent enumtype has namespace mangled in + String *etype = Getattr(parent, "enumtype"); + // we have to directly call the c wrapper function, as the + // R wrapper to the enum is designed to be used after the enum + // structures have been created on the R side. This means + // that we'll need to construct a .Call expression + // change the type for variableWrapper + if (debugMode) { + Printf(stdout, " type set: %s\n", etype); + } + Setattr(n, "type", etype); + if (!getCurrentClass()) { + newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname); + // Strange hack to change the name + Setattr(n, "name", Getattr(n, "value")); + Setattr(n, "sym:name", newsymname); + variableWrapper(n); + value = Swig_name_get(NSPACE_TODO, newsymname); + } else { + String *enumClassPrefix = getEnumClassPrefix(); + newsymname = Swig_name_member(0, enumClassPrefix, symname); + Setattr(n, "name", Getattr(n, "value")); + Setattr(n, "sym:name", newsymname); + variableWrapper(n); + value = Swig_name_get(NSPACE_TODO, newsymname); + } + value = Swig_name_wrapper(value); + Replace(value, "_wrap", "R_swig", DOH_REPLACE_FIRST); - -/*************************************************************************************/ - - - - - + String *valuecall=NewString(""); + Printv(valuecall, ".Call('", value, "',FALSE, PACKAGE='", Rpackage, "')", NIL); + Delete(value); + return valuecall; +} diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 2a3128472..6a1e16d5d 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -131,12 +131,10 @@ enum autodoc_t { static const char *usage = "\ Ruby Options (available with -ruby)\n\ -autorename - Enable renaming of classes and methods to follow Ruby coding standards\n\ - -cppcast - Enable C++ casting operators (default)\n\ -globalmodule - Wrap everything into the global module\n\ -initname - Set entry function to Init_ (used by `require')\n\ -minherit - Attempt to support multiple inheritance\n\ -noautorename - Disable renaming of classes and methods (default)\n\ - -nocppcast - Disable C++ casting operators, useful for generating bugs\n\ -prefix - Set a prefix to be prepended to all names\n\ "; @@ -257,32 +255,22 @@ private: autodoc = make_autodoc(n, ad_type); have_auto = (autodoc && Len(autodoc) > 0); } - // If there is more than one line then make docstrings like this: - // - // This is line1 - // And here is line2 followed by the rest of them - // - // otherwise, put it all on a single line - // + + if (have_auto || have_ds) + doc = NewString("/*"); + if (have_auto && have_ds) { // Both autodoc and docstring are present - doc = NewString(""); - Printv(doc, "\n", autodoc, "\n", str, NIL); + Printv(doc, "\n", autodoc, "\n", str, "\n", NIL); } else if (!have_auto && have_ds) { // only docstring - if (Strchr(str, '\n') == 0) { - doc = NewString(str); - } else { - doc = NewString(""); - Printv(doc, str, NIL); - } + Printv(doc, str, NIL); } else if (have_auto && !have_ds) { // only autodoc - if (Strchr(autodoc, '\n') == 0) { - doc = NewStringf("%s", autodoc); - } else { - doc = NewString(""); - Printv(doc, "\n", autodoc, NIL); - } - } else + Printv(doc, "\n", autodoc, "\n", NIL); + } else { doc = NewString(""); + } + + if (have_auto || have_ds) + Append(doc, "*/\n"); // Save the generated strings in the parse tree in case they are used later // by post processing tools @@ -302,13 +290,14 @@ private: * The "lname" attribute in each parameter in plist will be contain a parameter name * ----------------------------------------------------------------------------- */ - void addMissingParameterNames(ParmList *plist, int arg_offset) { + void addMissingParameterNames(Node* n, ParmList *plist, int arg_offset) { Parm *p = plist; int i = arg_offset; while (p) { if (!Getattr(p, "lname")) { - String *pname = Swig_cparm_name(p, i); - Delete(pname); + String *name = makeParameterName(n, p, i); + Setattr(p, "lname", name); + Delete(name); } i++; p = nextSibling(p); @@ -327,10 +316,10 @@ private: Parm *p; Parm *pnext; int lines = 0; - int start_arg_num = is_wrapping_class() ? 1 : 0; + int arg_num = is_wrapping_class() ? 1 : 0; const int maxwidth = 80; - addMissingParameterNames(plist, start_arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms + addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms Swig_typemap_attach_parms("in", plist, 0); Swig_typemap_attach_parms("doc", plist, 0); @@ -340,7 +329,7 @@ private: return doc; } - for (p = plist; p; p = pnext) { + for (p = plist; p; p = pnext, arg_num++) { String *tm = Getattr(p, "tmap:in"); if (tm) { @@ -363,9 +352,10 @@ private: } // Note: the generated name should be consistent with that in kwnames[] - name = name ? name : Getattr(p, "name"); - name = name ? name : Getattr(p, "lname"); - name = Swig_name_make(p, 0, name, 0, 0); // rename parameter if a keyword + String *made_name = 0; + if (!name) { + name = made_name = makeParameterName(n, p, arg_num); + } type = type ? type : Getattr(p, "type"); value = value ? value : Getattr(p, "value"); @@ -416,7 +406,7 @@ private: Printf(doc, "=%s", value); } Delete(type_str); - Delete(name); + Delete(made_name); } if (pdocs) Setattr(n, "feature:pdocs", pdocs); @@ -436,7 +426,7 @@ private: String *make_autodoc(Node *n, autodoc_t ad_type) { int extended = 0; - // If the function is overloaded then this funciton is called + // If the function is overloaded then this function is called // for the last one. Rewind to the first so the docstrings are // in order. while (Getattr(n, "sym:previousSibling")) @@ -522,7 +512,7 @@ private: last_mode = ad_type; last_autodoc = Copy(methodName); - String *doc = NewString("/*\n"); + String *doc = NewString(""); int counter = 0; bool skipAuto = false; Node* on = n; @@ -762,7 +752,6 @@ private: n = Getattr(n, "sym:nextSibling"); } - Append(doc, "\n*/\n"); Delete(full_name); Delete(class_name); Delete(super_names); @@ -844,7 +833,6 @@ public: virtual void main(int argc, char *argv[]) { - int cppcast = 1; int autorename = 0; /* Set location of SWIG library */ @@ -883,12 +871,6 @@ public: multipleInheritance = true; director_multiple_inheritance = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i], "-cppcast") == 0) { - cppcast = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nocppcast") == 0) { - cppcast = 0; - Swig_mark_arg(i); } else if (strcmp(argv[i], "-autorename") == 0) { autorename = 1; Swig_mark_arg(i); @@ -907,15 +889,17 @@ public: } } else if (strcmp(argv[i], "-help") == 0) { Printf(stdout, "%s\n", usage); + } else if (strcmp(argv[i], "-cppcast") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]); + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-nocppcast") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]); + Swig_mark_arg(i); + SWIG_exit(EXIT_FAILURE); } } } - if (cppcast) { - /* Turn on cppcast mode */ - Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0); - } - if (autorename) { /* Turn on the autorename mode */ Preprocessor_define((DOH *) "SWIG_RUBY_AUTORENAME", 0); @@ -1316,7 +1300,13 @@ public: Iterator alias = First(aliases); while (alias.item) { if (Len(alias.item) > 0) { - if (multipleInheritance) { + if (current == NO_CPP) { + if (useGlobalModule) { + Printv(f_init, tab4, "rb_define_alias(rb_cObject, \"", alias.item, "\", \"", iname, "\");\n", NIL); + } else { + Printv(f_init, tab4, "rb_define_alias(rb_singleton_class(", modvar, "), \"", alias.item, "\", \"", iname, "\");\n", NIL); + } + } else if (multipleInheritance) { Printv(klass->init, tab4, "rb_define_alias(", klass->mImpl, ", \"", alias.item, "\", \"", iname, "\");\n", NIL); } else { Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias.item, "\", \"", iname, "\");\n", NIL); @@ -1419,9 +1409,8 @@ public: case DESTRUCTOR: case CLASS_CONST: case STATIC_VAR: - assert(false); // Should not have gotten here for these types default: - assert(false); + assert(false); // Should not have gotten here for these types } defineAliases(n, iname); @@ -2926,7 +2915,7 @@ public: Wrapper *w = NewWrapper(); String *call; String *basetype = Getattr(parent, "classtype"); - String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); + String *target = Swig_method_decl(0, decl, classname, parms, 0); call = Swig_csuperclass_call(0, basetype, superparms); Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call); Delete(target); @@ -2937,7 +2926,7 @@ public: /* constructor header */ { - String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); + String *target = Swig_method_decl(0, decl, classname, parms, 1); Printf(f_directors_h, " %s;\n", target); Delete(target); } @@ -3047,7 +3036,7 @@ public: if (argc > 0) { Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), %d%s);\n", Swig_cresult_name(), methodName, argc, args); } else { - Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, NULL);\n", Swig_cresult_name(), methodName); + Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, Qnil);\n", Swig_cresult_name(), methodName); } if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n"); } @@ -3103,16 +3092,20 @@ public: String *pclassname = NewStringf("SwigDirector_%s", classname); String *qualified_name = NewStringf("%s::%s", pclassname, name); SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); - target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); + target = Swig_method_decl(rtype, decl, qualified_name, l, 0); Printf(w->def, "%s", target); Delete(qualified_name); Delete(target); /* header declaration */ - target = Swig_method_decl(rtype, decl, name, l, 0, 1); + target = Swig_method_decl(rtype, decl, name, l, 1); Printf(declaration, " virtual %s", target); Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { @@ -3151,9 +3144,19 @@ public: * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { - Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL); + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { + String *cres = SwigType_lstr(returntype, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); } } @@ -3175,7 +3178,7 @@ public: Swig_director_parms_fixup(l); Swig_typemap_attach_parms("in", l, 0); - Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorin", l, w); Swig_typemap_attach_parms("directorargout", l, w); char source[256]; @@ -3288,7 +3291,7 @@ public: } /* declare Ruby return value */ - String *value_result = NewStringf("VALUE %s", Swig_cresult_name()); + String *value_result = NewStringf("VALUE SWIGUNUSED %s", Swig_cresult_name()); Wrapper_add_local(w, Swig_cresult_name(), value_result); Delete(value_result); diff --git a/Source/Modules/scilab.cxx b/Source/Modules/scilab.cxx index c44c92d6c..23e45f787 100644 --- a/Source/Modules/scilab.cxx +++ b/Source/Modules/scilab.cxx @@ -18,13 +18,14 @@ static const int SCILAB_VARIABLE_NAME_CHAR_MAX = SCILAB_IDENTIFIER_NAME_CHAR_MAX static const char *usage = (char *) " \ Scilab options (available with -scilab)\n \ - -builder - Generate a Scilab builder script\n \ - -buildercflags - Add to the builder compiler flags\n \ - -builderflagscript - Set the Scilab script to use by builder to configure the build flags\n \ - -builderldflags - Add to the builder linker flags\n \ - -buildersources - Add the (comma separated) files to the builder sources\n \ - -builderverbositylevel - Set the builder verbosity level to (default 0: off, 2: high)\n \ - -gatewayxml - Generate gateway xml with the given \n \ + -builder - Generate a Scilab builder script\n \ + -buildercflags - Add to the builder compiler flags\n \ + -builderflagscript - Set the Scilab script to use by builder to configure the build flags\n \ + -builderldflags - Add to the builder linker flags\n \ + -buildersources - Add the (comma separated) files to the builder sources\n \ + -builderverbositylevel - Set the builder verbosity level to (default 0: off, 2: high)\n \ + -gatewayxml - Generate gateway xml with the given \n \ + -targetversion - Generate for Scilab target (major) version (default: 5)\n \ \n"; @@ -39,6 +40,8 @@ protected: String *variablesCode; + int targetVersion; + bool generateBuilder; File *builderFile; String *builderCode; @@ -71,6 +74,7 @@ public: * ----------------------------------------------------------------------*/ virtual void main(int argc, char *argv[]) { + targetVersion = 5; generateBuilder = false; sourceFileList = NewList(); @@ -95,48 +99,54 @@ public: /* Manage command line arguments */ for (int argIndex = 1; argIndex < argc; argIndex++) { if (argv[argIndex] != NULL) { - if (strcmp(argv[argIndex], "-help") == 0) { - Printf(stdout, "%s\n", usage); - } else if (strcmp(argv[argIndex], "-builder") == 0) { - Swig_mark_arg(argIndex); - generateBuilder = true; - createLoader = false; - } else if (strcmp(argv[argIndex], "-buildersources") == 0) { - if (argv[argIndex + 1] != NULL) { - Swig_mark_arg(argIndex); - char *sourceFile = strtok(argv[argIndex + 1], ","); - while (sourceFile != NULL) { - Insert(sourceFileList, Len(sourceFileList), sourceFile); - sourceFile = strtok(NULL, ","); - } - Swig_mark_arg(argIndex + 1); - } - } else if (strcmp(argv[argIndex], "-buildercflags") == 0) { - Swig_mark_arg(argIndex); - if (argv[argIndex + 1] != NULL) { - Insert(cflags, Len(cflags), argv[argIndex + 1]); - Swig_mark_arg(argIndex + 1); - } - } else if (strcmp(argv[argIndex], "-builderldflags") == 0) { - Swig_mark_arg(argIndex); - if (argv[argIndex + 1] != NULL) { - Insert(ldflags, Len(ldflags), argv[argIndex + 1]); - Swig_mark_arg(argIndex + 1); - } - } else if (strcmp(argv[argIndex], "-builderverbositylevel") == 0) { - Swig_mark_arg(argIndex); - verboseBuildLevel = NewString(argv[argIndex + 1]); - Swig_mark_arg(argIndex + 1); - } else if (strcmp(argv[argIndex], "-builderflagscript") == 0) { - Swig_mark_arg(argIndex); - buildFlagsScript = NewString(argv[argIndex + 1]); - Swig_mark_arg(argIndex + 1); - } else if (strcmp(argv[argIndex], "-gatewayxml") == 0) { - Swig_mark_arg(argIndex); - createGatewayXML = true; - gatewayID = NewString(argv[argIndex + 1]); - Swig_mark_arg(argIndex + 1); - } + if (strcmp(argv[argIndex], "-help") == 0) { + Printf(stdout, "%s\n", usage); + } else if (strcmp(argv[argIndex], "-builder") == 0) { + Swig_mark_arg(argIndex); + generateBuilder = true; + createLoader = false; + } else if (strcmp(argv[argIndex], "-buildersources") == 0) { + if (argv[argIndex + 1] != NULL) { + Swig_mark_arg(argIndex); + char *sourceFile = strtok(argv[argIndex + 1], ","); + while (sourceFile != NULL) { + Insert(sourceFileList, Len(sourceFileList), sourceFile); + sourceFile = strtok(NULL, ","); + } + Swig_mark_arg(argIndex + 1); + } + } else if (strcmp(argv[argIndex], "-buildercflags") == 0) { + Swig_mark_arg(argIndex); + if (argv[argIndex + 1] != NULL) { + Insert(cflags, Len(cflags), argv[argIndex + 1]); + Swig_mark_arg(argIndex + 1); + } + } else if (strcmp(argv[argIndex], "-builderldflags") == 0) { + Swig_mark_arg(argIndex); + if (argv[argIndex + 1] != NULL) { + Insert(ldflags, Len(ldflags), argv[argIndex + 1]); + Swig_mark_arg(argIndex + 1); + } + } else if (strcmp(argv[argIndex], "-builderverbositylevel") == 0) { + Swig_mark_arg(argIndex); + verboseBuildLevel = NewString(argv[argIndex + 1]); + Swig_mark_arg(argIndex + 1); + } else if (strcmp(argv[argIndex], "-builderflagscript") == 0) { + Swig_mark_arg(argIndex); + buildFlagsScript = NewString(argv[argIndex + 1]); + Swig_mark_arg(argIndex + 1); + } else if (strcmp(argv[argIndex], "-gatewayxml") == 0) { + Swig_mark_arg(argIndex); + createGatewayXML = true; + gatewayID = NewString(argv[argIndex + 1]); + Swig_mark_arg(argIndex + 1); + } else if (strcmp(argv[argIndex], "-targetversion") == 0) { + if (argv[argIndex + 1] != NULL) { + Swig_mark_arg(argIndex); + targetVersion = atoi(argv[argIndex + 1]); + Swig_mark_arg(argIndex + 1); + } + } } } @@ -412,7 +422,7 @@ public: emit_return_variable(node, functionReturnType, wrapper); /* Return the function value if necessary */ - String *functionReturnTypemap = Swig_typemap_lookup_out("out", node, "result", wrapper, functionActionCode); + String *functionReturnTypemap = Swig_typemap_lookup_out("out", node, Swig_cresult_name(), wrapper, functionActionCode); if (functionReturnTypemap) { // Result is actually the position of output value on stack if (Len(functionReturnTypemap) > 0) { @@ -471,6 +481,13 @@ public: } } + /* See if there is any return cleanup code */ + String *tm; + if ((tm = Swig_typemap_lookup("ret", node, Swig_cresult_name(), 0))) { + Replaceall(tm, "$source", Swig_cresult_name()); + Printf(wrapper->code, "%s\n", tm); + Delete(tm); + } /* Close the function(ok) */ Printv(wrapper->code, "return SWIG_OK;\n", NIL); @@ -479,7 +496,7 @@ public: /* Add the failure cleanup code */ /* TODO */ - /* Final substititions if applicable */ + /* Final substitutions if applicable */ Replaceall(wrapper->code, "$symname", functionName); /* Set CheckInputArgument and CheckOutputArgument input arguments */ @@ -777,57 +794,61 @@ public: /* ----------------------------------------------------------------------- * checkIdentifierName() - * Truncates (and displays a warning) for too long identifier names - * (applies on functions, variables, constants...) - * (Scilab identifiers names are limited to 24 chars max) + * If Scilab target version is lower than 6: + * truncates (and displays a warning) too long member identifier names + * (applies on members of structs, classes...) + * (Scilab 5 identifier names are limited to 24 chars max) * ----------------------------------------------------------------------- */ String *checkIdentifierName(String *name, int char_size_max) { String *scilabIdentifierName; - if (Len(name) > char_size_max) { - scilabIdentifierName = DohNewStringWithSize(name, char_size_max); - Swig_warning(WARN_SCILAB_TRUNCATED_NAME, input_file, line_number, - "Identifier name '%s' exceeds 24 characters and has been truncated to '%s'.\n", name, scilabIdentifierName); - } else + if (targetVersion <= 5) { + if (Len(name) > char_size_max) { + scilabIdentifierName = DohNewStringWithSize(name, char_size_max); + Swig_warning(WARN_SCILAB_TRUNCATED_NAME, input_file, line_number, + "Identifier name '%s' exceeds 24 characters and has been truncated to '%s'.\n", name, scilabIdentifierName); + } else scilabIdentifierName = name; - return scilabIdentifierName; + } else { + scilabIdentifierName = DohNewString(name); + } + return scilabIdentifierName; } /* ----------------------------------------------------------------------- * checkMemberIdentifierName() - * Truncates (and displays a warning) too long member identifier names - * (applies on members of structs, classes...) - * (Scilab identifiers names are limited to 24 chars max) + * If Scilab target version is lower than 6: + * truncates (and displays a warning) too long member identifier names + * (applies on members of structs, classes...) + * (Scilab 5 identifier names are limited to 24 chars max) * ----------------------------------------------------------------------- */ void checkMemberIdentifierName(Node *node, int char_size_max) { + if (targetVersion <= 5) { + String *memberName = Getattr(node, "sym:name"); + Node *containerNode = parentNode(node); + String *containerName = Getattr(containerNode, "sym:name"); + int lenContainerName = Len(containerName); + int lenMemberName = Len(memberName); - String *memberName = Getattr(node, "sym:name"); + if (lenContainerName + lenMemberName + 1 > char_size_max) { + int lenScilabMemberName = char_size_max - lenContainerName - 1; - Node *containerNode = parentNode(node); - String *containerName = Getattr(containerNode, "sym:name"); - - int lenContainerName = Len(containerName); - int lenMemberName = Len(memberName); - - if (lenContainerName + lenMemberName + 1 > char_size_max) { - int lenScilabMemberName = char_size_max - lenContainerName - 1; - - if (lenScilabMemberName > 0) { - String *scilabMemberName = DohNewStringWithSize(memberName, lenScilabMemberName); - Setattr(node, "sym:name", scilabMemberName); - Swig_warning(WARN_SCILAB_TRUNCATED_NAME, input_file, line_number, - "Wrapping functions names for member '%s.%s' will exceed 24 characters, " - "so member name has been truncated to '%s'.\n", containerName, memberName, scilabMemberName); - } else - Swig_error(input_file, line_number, - "Wrapping functions names for member '%s.%s' will exceed 24 characters, " - "please rename the container of member '%s'.\n", containerName, memberName, containerName); + if (lenScilabMemberName > 0) { + String *scilabMemberName = DohNewStringWithSize(memberName, lenScilabMemberName); + Setattr(node, "sym:name", scilabMemberName); + Swig_warning(WARN_SCILAB_TRUNCATED_NAME, input_file, line_number, + "Wrapping functions names for member '%s.%s' will exceed 24 characters, " + "so member name has been truncated to '%s'.\n", containerName, memberName, scilabMemberName); + } else { + Swig_error(input_file, line_number, + "Wrapping functions names for member '%s.%s' will exceed 24 characters, " + "please rename the container of member '%s'.\n", containerName, memberName, containerName); + } + } } } - - /* ----------------------------------------------------------------------- * addHelperFunctions() * ----------------------------------------------------------------------- */ @@ -1006,8 +1027,14 @@ public: Printf(gatewayHeader, "\n"); gatewayHeaderV6 = NewString(""); + Printf(gatewayHeaderV6, "#ifdef __cplusplus\n"); + Printf(gatewayHeaderV6, "extern \"C\" {\n"); + Printf(gatewayHeaderV6, "#endif\n"); Printf(gatewayHeaderV6, "#include \"c_gateway_prototype.h\"\n"); Printf(gatewayHeaderV6, "#include \"addfunction.h\"\n"); + Printf(gatewayHeaderV6, "#ifdef __cplusplus\n"); + Printf(gatewayHeaderV6, "}\n"); + Printf(gatewayHeaderV6, "#endif\n"); Printf(gatewayHeaderV6, "\n"); Printf(gatewayHeaderV6, "#define MODULE_NAME L\"%s\"\n", gatewayLibraryName); Printf(gatewayHeaderV6, "#ifdef __cplusplus\n"); diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index a91cd22c1..ba710c0ce 100644 --- a/Source/Modules/swigmain.cxx +++ b/Source/Modules/swigmain.cxx @@ -26,79 +26,64 @@ can be dynamically loaded in future versions. */ extern "C" { - Language *swig_tcl(void); - Language *swig_python(void); - Language *swig_perl5(void); - Language *swig_ruby(void); + Language *swig_c(void); + Language *swig_csharp(void); + Language *swig_d(void); + Language *swig_go(void); Language *swig_guile(void); - Language *swig_modula3(void); - Language *swig_mzscheme(void); Language *swig_java(void); - Language *swig_php(void); - Language *swig_php4(void); + Language *swig_javascript(void); + Language *swig_lua(void); + Language *swig_mzscheme(void); Language *swig_ocaml(void); Language *swig_octave(void); - Language *swig_pike(void); - Language *swig_sexp(void); - Language *swig_xml(void); - Language *swig_chicken(void); - Language *swig_csharp(void); - Language *swig_allegrocl(void); - Language *swig_lua(void); - Language *swig_clisp(void); - Language *swig_cffi(void); - Language *swig_uffi(void); + Language *swig_perl5(void); + Language *swig_php(void); + Language *swig_python(void); Language *swig_r(void); - Language *swig_c(void); + Language *swig_ruby(void); Language *swig_scilab(void); - Language *swig_go(void); - Language *swig_d(void); - Language *swig_javascript(void); + Language *swig_tcl(void); + Language *swig_xml(void); } -struct swig_module { - const char *name; - ModuleFactory fac; - const char *help; -}; - /* Association of command line options to language modules. Place an entry for new language modules here, keeping the list sorted alphabetically. */ -static swig_module modules[] = { - {"-allegrocl", swig_allegrocl, "ALLEGROCL"}, - {"-c", swig_c, "C"}, - {"-chicken", swig_chicken, "CHICKEN"}, - {"-clisp", swig_clisp, "CLISP"}, - {"-cffi", swig_cffi, "CFFI"}, - {"-csharp", swig_csharp, "C#"}, - {"-d", swig_d, "D"}, - {"-go", swig_go, "Go"}, - {"-guile", swig_guile, "Guile"}, - {"-java", swig_java, "Java"}, - {"-javascript", swig_javascript, "Javascript"}, - {"-lua", swig_lua, "Lua"}, - {"-modula3", swig_modula3, "Modula 3"}, - {"-mzscheme", swig_mzscheme, "Mzscheme"}, - {"-ocaml", swig_ocaml, "Ocaml"}, - {"-octave", swig_octave, "Octave"}, - {"-perl", swig_perl5, "Perl"}, - {"-perl5", swig_perl5, 0}, - {"-php", swig_php, "PHP"}, - {"-php4", swig_php4, 0}, - {"-php5", swig_php, 0}, - {"-pike", swig_pike, "Pike"}, - {"-python", swig_python, "Python"}, - {"-r", swig_r, "R (aka GNU S)"}, - {"-ruby", swig_ruby, "Ruby"}, - {"-scilab", swig_scilab, "Scilab"}, - {"-sexp", swig_sexp, "Lisp S-Expressions"}, - {"-tcl", swig_tcl, "Tcl"}, - {"-tcl8", swig_tcl, 0}, - {"-uffi", swig_uffi, "Common Lisp / UFFI"}, - {"-xml", swig_xml, "XML"}, - {NULL, NULL, NULL} +static TargetLanguageModule modules[] = { + {"-allegrocl", NULL, "ALLEGROCL", Disabled}, + {"-c", swig_c, "C", Experimental}, + {"-chicken", NULL, "CHICKEN", Disabled}, + {"-clisp", NULL, "CLISP", Disabled}, + {"-cffi", NULL, "CFFI", Disabled}, + {"-csharp", swig_csharp, "C#", Supported}, + {"-d", swig_d, "D", Supported}, + {"-go", swig_go, "Go", Supported}, + {"-guile", swig_guile, "Guile", Supported}, + {"-java", swig_java, "Java", Supported}, + {"-javascript", swig_javascript, "Javascript", Supported}, + {"-lua", swig_lua, "Lua", Supported}, + {"-modula3", NULL, "Modula 3", Disabled}, + {"-mzscheme", swig_mzscheme, "MzScheme/Racket", Experimental}, + {"-ocaml", swig_ocaml, "OCaml", Experimental}, + {"-octave", swig_octave, "Octave", Supported}, + {"-perl", swig_perl5, NULL, Supported}, + {"-perl5", swig_perl5, "Perl 5", Supported}, + {"-php", swig_php, NULL, Supported}, + {"-php5", NULL, "PHP 5", Disabled}, + {"-php7", swig_php, "PHP 7", Supported}, + {"-pike", NULL, "Pike", Disabled}, + {"-python", swig_python, "Python", Supported}, + {"-r", swig_r, "R (aka GNU S)", Supported}, + {"-ruby", swig_ruby, "Ruby", Supported}, + {"-scilab", swig_scilab, "Scilab", Supported}, + {"-sexp", NULL, "Lisp S-Expressions", Disabled}, + {"-tcl", swig_tcl, NULL, Supported}, + {"-tcl8", swig_tcl, "Tcl 8", Supported}, + {"-uffi", NULL, "Common Lisp / UFFI", Disabled}, + {"-xml", swig_xml, "XML", Supported}, + {NULL, NULL, NULL, Disabled} }; #ifdef MACSWIG @@ -106,10 +91,6 @@ static swig_module modules[] = { #include #endif -#ifndef SWIG_LANG -#define SWIG_LANG "-python" -#endif - //----------------------------------------------------------------- // main() // @@ -119,13 +100,14 @@ static swig_module modules[] = { void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, char ***nargv) { if (!env) { *nargc = oargc; - *nargv = oargv; + *nargv = (char **)malloc(sizeof(char *) * (oargc + 1)); + memcpy(*nargv, oargv, sizeof(char *) * (oargc + 1)); return; } int argc = 1; int arge = oargc + 1024; - char **argv = (char **) malloc(sizeof(char *) * (arge)); + char **argv = (char **) malloc(sizeof(char *) * (arge + 1)); char *buffer = (char *) malloc(2048); char *b = buffer; char *be = b + 1023; @@ -147,49 +129,139 @@ void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, ch for (int i = 1; (i < oargc) && (argc < arge); ++i, ++argc) { argv[argc] = oargv[i]; } + argv[argc] = NULL; *nargc = argc; *nargv = argv; } +static void insert_option(int *argc, char ***argv, int index, char const *start, char const *end) { + int new_argc = *argc; + char **new_argv = *argv; + size_t option_len = end - start; + + // Preserve the NULL pointer at argv[argc] + new_argv = (char **)realloc(new_argv, (new_argc + 2) * sizeof(char *)); + memmove(&new_argv[index + 1], &new_argv[index], sizeof(char *) * (new_argc + 1 - index)); + new_argc++; + + new_argv[index] = (char *)malloc(option_len + 1); + memcpy(new_argv[index], start, option_len); + new_argv[index][option_len] = '\0'; + + *argc = new_argc; + *argv = new_argv; +} + +static void merge_options_files(int *argc, char ***argv) { + static const int BUFFER_SIZE = 4096; + char buffer[BUFFER_SIZE]; + int i; + int insert; + char **new_argv = *argv; + int new_argc = *argc; + FILE *f; + + i = 1; + while (i < new_argc) { + if (new_argv[i] && new_argv[i][0] == '@' && (f = fopen(&new_argv[i][1], "r"))) { + char c; + char *b; + char *be = &buffer[BUFFER_SIZE]; + int quote = 0; + bool escape = false; + + new_argc--; + memmove(&new_argv[i], &new_argv[i + 1], sizeof(char *) * (new_argc - i)); + insert = i; + b = buffer; + + while ((c = fgetc(f)) != EOF) { + if (escape) { + if (b != be) { + *b = c; + ++b; + } + escape = false; + } else if (c == '\\') { + escape = true; + } else if (!quote && (c == '\'' || c == '"')) { + quote = c; + } else if (quote && c == quote) { + quote = 0; + } else if (isspace(c) && !quote) { + if (b != buffer) { + insert_option(&new_argc, &new_argv, insert, buffer, b); + insert++; + + b = buffer; + } + } else if (b != be) { + *b = c; + ++b; + } + } + if (b != buffer) + insert_option(&new_argc, &new_argv, insert, buffer, b); + fclose(f); + } else { + ++i; + } + } + + *argv = new_argv; + *argc = new_argc; +} + int main(int margc, char **margv) { int i; - Language *dl = 0; - ModuleFactory fac = 0; + const TargetLanguageModule *language_module = 0; int argc; char **argv; SWIG_merge_envopt(getenv("SWIG_FEATURES"), margc, margv, &argc, &argv); + merge_options_files(&argc, &argv); #ifdef MACSWIG SIOUXSettings.asktosaveonclose = false; argc = ccommand(&argv); #endif - /* Register built-in modules */ - for (i = 0; modules[i].name; i++) { - Swig_register_module(modules[i].name, modules[i].fac); - } - Swig_init_args(argc, argv); /* Get options */ for (i = 1; i < argc; i++) { if (argv[i]) { - fac = Swig_find_module(argv[i]); - if (fac) { - dl = (fac) (); - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nolang") == 0) { - dl = new Language; + bool is_target_language_module = false; + for (int j = 0; modules[j].name; j++) { + if (strcmp(modules[j].name, argv[i]) == 0) { + language_module = &modules[j]; + is_target_language_module = true; + break; + } + } + if (is_target_language_module) { Swig_mark_arg(i); + if (language_module->status == Disabled) { + if (language_module->help) + Printf(stderr, "Target language option %s (%s) is no longer supported.\n", language_module->name, language_module->help); + else + Printf(stderr, "Target language option %s is no longer supported.\n", language_module->name); + SWIG_exit(EXIT_FAILURE); + } } else if ((strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0)) { if (strcmp(argv[i], "--help") == 0) strcpy(argv[i], "-help"); - Printf(stdout, "Target Language Options\n"); + Printf(stdout, "Supported Target Language Options\n"); for (int j = 0; modules[j].name; j++) { - if (modules[j].help) { + if (modules[j].help && modules[j].status == Supported) { + Printf(stdout, " %-15s - Generate %s wrappers\n", modules[j].name, modules[j].help); + } + } + Printf(stdout, "\nExperimental Target Language Options\n"); + for (int j = 0; modules[j].name; j++) { + if (modules[j].help && modules[j].status == Experimental) { Printf(stdout, " %-15s - Generate %s wrappers\n", modules[j].name, modules[j].help); } } @@ -197,14 +269,8 @@ int main(int margc, char **margv) { } } } - if (!dl) { - fac = Swig_find_module(SWIG_LANG); - if (fac) { - dl = (fac) (); - } - } - int res = SWIG_main(argc, argv, dl); + int res = SWIG_main(argc, argv, language_module); return res; } diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index 34763cc09..583cb13fe 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -214,8 +214,8 @@ public: virtual Hash* symbolAddScope(const_String_or_char_ptr scope); virtual Hash* symbolScopeLookup(const_String_or_char_ptr scope); virtual Hash* symbolScopePseudoSymbolLookup(const_String_or_char_ptr scope); - virtual Node *classLookup(const SwigType *s) const; /* Class lookup */ - virtual Node *enumLookup(SwigType *s); /* Enum lookup */ + static Node *classLookup(const SwigType *s); /* Class lookup */ + static Node *enumLookup(SwigType *s); /* Enum lookup */ virtual int abstractClassTest(Node *n); /* Is class really abstract? */ virtual int is_assignable(Node *n); /* Is variable assignable? */ virtual String *runtimeCode(); /* returns the language specific runtime code */ @@ -342,10 +342,11 @@ protected: /* Director language module */ int director_language; + /* Used to translate Doxygen comments to target documentation format */ + class DoxygenTranslator *doxygenTranslator; + private: Hash *symtabs; /* symbol tables */ - Hash *classtypes; - Hash *enumtypes; int overloading; int multiinput; int cplus_runtime; @@ -353,7 +354,21 @@ private: static Language *this_; }; -int SWIG_main(int, char **, Language *); +extern "C" { + void SWIG_typemap_lang(const char *); + typedef Language *(*ModuleFactory) (void); +} + +enum Status {Disabled, Experimental, Supported}; + +struct TargetLanguageModule { + const char *name; + ModuleFactory fac; + const char *help; + Status status; +}; + +int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm); void emit_parameter_variables(ParmList *l, Wrapper *f); void emit_return_variable(Node *n, SwigType *rt, Wrapper *f); void SWIG_exit(int); /* use EXIT_{SUCCESS,FAILURE} */ @@ -368,15 +383,15 @@ List *SWIG_output_files(); void SWIG_library_directory(const char *); int emit_num_arguments(ParmList *); int emit_num_required(ParmList *); -int emit_isvarargs(ParmList *); +int emit_isvarargs(ParmList *p); +bool emit_isvarargs_function(Node *n); void emit_attach_parmmaps(ParmList *, Wrapper *f); void emit_mark_varargs(ParmList *l); String *emit_action(Node *n); int emit_action_code(Node *n, String *wrappercode, String *action); void Swig_overload_check(Node *n); -String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *); +String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *, const_String_or_char_ptr fmt_fastdispatch = 0); String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *); -String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *); List *Swig_overload_rank(Node *n, bool script_lang_wrapping); SwigType *cplus_value_type(SwigType *t); @@ -385,20 +400,12 @@ String *Swig_csuperclass_call(String *base, String *method, ParmList *l); String *Swig_class_declaration(Node *n, String *name); String *Swig_class_name(Node *n); String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms); -String *Swig_method_decl(SwigType *rtype, SwigType *decl, const_String_or_char_ptr id, List *args, int strip, int values); +String *Swig_method_decl(SwigType *return_base_type, SwigType *decl, const_String_or_char_ptr id, List *args, int default_args); String *Swig_director_declaration(Node *n); void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f); void Swig_director_parms_fixup(ParmList *parms); /* directors.cxx end */ -extern "C" { - void SWIG_typemap_lang(const char *); - typedef Language *(*ModuleFactory) (void); -} - -void Swig_register_module(const char *name, ModuleFactory fac); -ModuleFactory Swig_find_module(const char *name); - /* Utilities */ int is_public(Node *n); diff --git a/Source/Modules/tcl8.cxx b/Source/Modules/tcl8.cxx index 1227af79c..7a78ede9b 100644 --- a/Source/Modules/tcl8.cxx +++ b/Source/Modules/tcl8.cxx @@ -15,7 +15,7 @@ #include "cparse.h" static const char *usage = "\ -Tcl 8 Options (available with -tcl)\n\ +Tcl 8 Options (available with -tcl8)\n\ -itcl - Enable ITcl support\n\ -nosafe - Leave out SafeInit module function.\n\ -prefix - Set a prefix to be prepended to all names\n\ @@ -76,7 +76,6 @@ public: * ------------------------------------------------------------ */ virtual void main(int argc, char *argv[]) { - int cppcast = 1; SWIG_library_directory("tcl"); @@ -106,22 +105,19 @@ public: } else if (strcmp(argv[i], "-nosafe") == 0) { nosafe = 1; Swig_mark_arg(i); - } else if (strcmp(argv[i], "-cppcast") == 0) { - cppcast = 1; - Swig_mark_arg(i); - } else if (strcmp(argv[i], "-nocppcast") == 0) { - cppcast = 0; - Swig_mark_arg(i); } else if (strcmp(argv[i], "-help") == 0) { fputs(usage, stdout); + } else if (strcmp(argv[i], "-cppcast") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]); + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-nocppcast") == 0) { + Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]); + Swig_mark_arg(i); + SWIG_exit(EXIT_FAILURE); } } } - if (cppcast) { - Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0); - } - Preprocessor_define("SWIGTCL 1", 0); // SWIGTCL8 is deprecated, and no longer documented. Preprocessor_define("SWIGTCL8 1", 0); diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index dc4d02bdd..57125fcbb 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -187,8 +187,10 @@ class TypePass:private Dispatcher { ilist = alist = NewList(); Append(ilist, bcls); } else { - Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname)); - Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname)); + if (!GetFlag(bcls, "feature:ignore")) { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname)); + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname)); + } } } break; @@ -209,8 +211,10 @@ class TypePass:private Dispatcher { ilist = alist = NewList(); Append(ilist, bcls); } else { - Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname)); - Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname)); + if (!GetFlag(bcls, "feature:ignore")) { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname)); + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname)); + } } } else { Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' undefined.\n", SwigType_namestr(bname)); @@ -566,6 +570,10 @@ class TypePass:private Dispatcher { SwigType_typedef_class(rname); Delete(rname); /* SwigType_typedef_class(name); */ + } else if (Strcmp(ttype, "cdecl") == 0) { + String *rname = SwigType_typedef_resolve_all(name); + SwigType_typedef_class(rname); + Delete(rname); } return SWIG_OK; } @@ -1195,10 +1203,7 @@ class TypePass:private Dispatcher { } else if (Strcmp(ntype, "enum") == 0) { SwigType_typedef_using(Getattr(n, "uname")); } else if (Strcmp(ntype, "template") == 0) { - /* - Printf(stdout, "usingDeclaration template %s --- %s\n", Getattr(n, "name"), Getattr(n, "uname")); SwigType_typedef_using(Getattr(n, "uname")); - */ } } } diff --git a/Source/Modules/uffi.cxx b/Source/Modules/uffi.cxx index d56ed3b1f..10a53a561 100644 --- a/Source/Modules/uffi.cxx +++ b/Source/Modules/uffi.cxx @@ -363,23 +363,24 @@ int UFFI::classHandler(Node *n) { for (c = firstChild(n); c; c = nextSibling(c)) { SwigType *type = Getattr(c, "type"); SwigType *decl = Getattr(c, "decl"); - type = Copy(type); - SwigType_push(type, decl); - String *lisp_type; + if (type) { + type = Copy(type); + SwigType_push(type, decl); + String *lisp_type; - if (Strcmp(nodeType(c), "cdecl")) { - Printf(stderr, "Structure %s has a slot that we can't deal with.\n", name); - Printf(stderr, "nodeType: %s, name: %s, type: %s\n", nodeType(c), Getattr(c, "name"), Getattr(c, "type")); - SWIG_exit(EXIT_FAILURE); + if (Strcmp(nodeType(c), "cdecl")) { + Printf(stderr, "Structure %s has a slot that we can't deal with.\n", name); + Printf(stderr, "nodeType: %s, name: %s, type: %s\n", nodeType(c), Getattr(c, "name"), Getattr(c, "type")); + SWIG_exit(EXIT_FAILURE); + } + + /* Printf(stdout, "Converting %s in %s\n", type, name); */ + lisp_type = get_ffi_type(n, type, Getattr(c, "sym:name")); + + Printf(f_cl, " (#.(%s \"%s\" :type :slot) %s)\n", identifier_converter, Getattr(c, "sym:name"), lisp_type); + + Delete(lisp_type); } - - - /* Printf(stdout, "Converting %s in %s\n", type, name); */ - lisp_type = get_ffi_type(n, type, Getattr(c, "sym:name")); - - Printf(f_cl, " (#.(%s \"%s\" :type :slot) %s)\n", identifier_converter, Getattr(c, "sym:name"), lisp_type); - - Delete(lisp_type); } // Language::classHandler(n); diff --git a/Source/Modules/utils.cxx b/Source/Modules/utils.cxx index a91ebe098..2964ed3a6 100644 --- a/Source/Modules/utils.cxx +++ b/Source/Modules/utils.cxx @@ -59,7 +59,7 @@ int is_non_virtual_protected_access(Node *n) { // When vtable is empty, the director class does not get emitted, so a check for an empty vtable should be done. // However, vtable is set in Language and so is not yet set when methods in Typepass call clean_overloaded() // which calls is_non_virtual_protected_access. So commented out below. - // Moving the director vtable creation into into Typepass should solve this problem. + // Moving the director vtable creation into Typepass should solve this problem. if (is_member_director_helper(parentNode, n) /* && Getattr(parentNode, "vtable")*/) result = 1; } diff --git a/Source/Modules/xml.cxx b/Source/Modules/xml.cxx index a69e7b043..5f090561a 100644 --- a/Source/Modules/xml.cxx +++ b/Source/Modules/xml.cxx @@ -144,8 +144,8 @@ public: Xml_print_kwargs(Getattr(obj, k)); } else if (Cmp(k, "parms") == 0 || Cmp(k, "pattern") == 0) { Xml_print_parmlist(Getattr(obj, k)); - } else if (Cmp(k, "catchlist") == 0) { - Xml_print_parmlist(Getattr(obj, k), "catchlist"); + } else if (Cmp(k, "catchlist") == 0 || Cmp(k, "templateparms") == 0) { + Xml_print_parmlist(Getattr(obj, k), Char(k)); } else { DOH *o; print_indent(0); diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index a183eecde..557b5482b 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -109,6 +109,19 @@ static String *cpp_include(const_String_or_char_ptr fn, int sysfile) { return s; } +static int is_digits(const String *str) { + const char *s = Char(str); + int isdigits = (*s != 0); + while (*s) { + if (!isdigit(*s)) { + isdigits = 0; + break; + } + s++; + } + return isdigits; +} + List *Preprocessor_depend(void) { return dependencies; } @@ -607,6 +620,34 @@ static List *find_args(String *s, int ismacro, String *macro_name) { skip_tochar(s, '\'', str); c = Getc(s); continue; + } else if (c == '/') { + /* Ensure comments are ignored by eating up the characters */ + c = Getc(s); + /* Handle / * ... * / type comments (multi-line) */ + if (c == '*') { + while ((c = Getc(s)) != EOF) { + if (c == '*') { + c = Getc(s); + if (c == '/' || c == EOF) + break; + } + } + c = Getc(s); + continue; + } + /* Handle // ... type comments (single-line) */ + if (c == '/') { + while ((c = Getc(s)) != EOF) { + if (c == '\n') { + break; + } + } + c = Getc(s); + continue; + } + /* ensure char is available in the stream as this was not a comment*/ + Ungetc(c, s); + c = '/'; } if ((c == ',') && (level == 0)) break; @@ -623,13 +664,8 @@ static List *find_args(String *s, int ismacro, String *macro_name) { goto unterm; } Chop(str); - if (Len(args) || Len(str)) - Append(args, str); + Append(args, str); Delete(str); - - /* if (Len(str) && (c != ')')) - Append(args,str); */ - if (c == ')') return args; c = Getc(s); @@ -800,11 +836,24 @@ static String *expand_macro(String *name, List *args, String *line_file) { Delete(vararg); } } + + if (args && margs && Len(margs) == 0 && Len(args) == 1 && Len(Getitem(args, 0)) == 0) { + /* FOO() can invoke a macro defined as FOO(X) as well as one defined FOO(). + * + * Handle this by removing the only argument if it's empty and the macro + * expects no arguments. + * + * We don't need to worry about varargs here - a varargs macro will always have + * Len(margs) >= 1, since the varargs are put in the final macro argument. + */ + Delitem(args, 0); + } + /* If there are arguments, see if they match what we were given */ - if (args && (margs) && (Len(margs) != Len(args))) { - if (Len(margs) > (1 + isvarargs)) + if (args && (!margs || Len(margs) != Len(args))) { + if (margs && Len(margs) > (1 + isvarargs)) Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects %d arguments\n", name, Len(margs) - isvarargs); - else if (Len(margs) == (1 + isvarargs)) + else if (margs && Len(margs) == (1 + isvarargs)) Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects 1 argument\n", name); else Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects no arguments\n", name); @@ -813,7 +862,7 @@ static String *expand_macro(String *name, List *args, String *line_file) { } /* If the macro expects arguments, but none were supplied, we leave it in place */ - if (!args && (margs) && Len(margs) > 0) { + if (!args && margs) { macro_level--; return NewString(name); } @@ -905,19 +954,21 @@ static String *expand_macro(String *name, List *args, String *line_file) { namelen = Len(aname); a = strstr(s, name); while (a) { - char ca = a[namelen + 1]; + char ca = a[namelen]; if (!isidchar((int) ca)) { /* Matched the entire vararg name, not just a prefix */ - t = a - 1; - if (*t == '\002') { - t--; - while (t >= s) { - if (isspace((int) *t)) - t--; - else if (*t == ',') { - *t = ' '; - } else - break; + if (a > s) { + t = a - 1; + if (*t == '\002') { + t--; + while (t >= s) { + if (isspace((int) *t)) + t--; + else if (*t == ',') { + *t = ' '; + } else + break; + } } } } @@ -1139,10 +1190,6 @@ static DOH *Preprocessor_replace(DOH *s) { args = find_args(s, 1, id); macro_additional_lines = Getline(s) - line; assert(macro_additional_lines >= 0); - if (!Len(args)) { - Delete(args); - args = 0; - } } else { args = 0; } @@ -1431,7 +1478,7 @@ String *Preprocessor_parse(String *s) { break; case 41: /* Build up the name of the preprocessor directive */ - if ((isspace(c) || (!isalpha(c)))) { + if ((isspace(c) || (!isidchar(c)))) { Clear(value); Clear(comment); if (c == '\n') { @@ -1450,7 +1497,7 @@ String *Preprocessor_parse(String *s) { Putc(c, id); break; - case 42: /* Strip any leading space before preprocessor value */ + case 42: /* Strip any leading space after the preprocessor directive (before preprocessor value) */ if (isspace(c)) { if (c == '\n') { Ungetc(c, s); @@ -1459,7 +1506,7 @@ String *Preprocessor_parse(String *s) { break; } state = 43; - /* no break intended here */ + /* FALL THRU */ case 43: /* Get preprocessor value */ @@ -1770,6 +1817,8 @@ String *Preprocessor_parse(String *s) { Swig_error(Getfile(s), Getline(id), "cpp debug: level = %d, startlevel = %d\n", level, start_level); } else if (Equal(id, "")) { /* Null directive */ + } else if (is_digits(id)) { + /* A gcc linemarker of the form '# linenum filename flags' (resulting from running gcc -E) */ } else { /* Ignore unknown preprocessor directives which are inside an inactive * conditional (github issue #394). */ diff --git a/Source/Preprocessor/expr.c b/Source/Preprocessor/expr.c index 6d22c8c5e..a36588983 100644 --- a/Source/Preprocessor/expr.c +++ b/Source/Preprocessor/expr.c @@ -188,12 +188,22 @@ static int reduce_op() { sp--; break; case SWIG_TOKEN_SLASH: - stack[sp - 2].value = stack[sp - 2].value / stack[sp].value; - sp -= 2; + if (stack[sp].value != 0) { + stack[sp - 2].value = stack[sp - 2].value / stack[sp].value; + sp -= 2; + } else { + errmsg = "Division by zero in expression"; + return 0; + } break; case SWIG_TOKEN_PERCENT: - stack[sp - 2].value = stack[sp - 2].value % stack[sp].value; - sp -= 2; + if (stack[sp].value != 0) { + stack[sp - 2].value = stack[sp - 2].value % stack[sp].value; + sp -= 2; + } else { + errmsg = "Modulo by zero in expression"; + return 0; + } break; case SWIG_TOKEN_LSHIFT: stack[sp - 2].value = stack[sp - 2].value << stack[sp].value; @@ -309,6 +319,10 @@ int Preprocessor_expr(DOH *s, int *error) { stack[sp].value = 0; stack[sp].svalue = 0; stack[sp].op = EXPR_VALUE; + } else if ((token == SWIG_TOKEN_FLOAT) || (token == SWIG_TOKEN_DOUBLE)) { + errmsg = "Floating point constant in preprocessor expression"; + *error = 1; + return 0; } else goto syntax_error; break; diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 9da4e0829..d6e5e0cdc 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -277,7 +277,7 @@ int Swig_cargs(Wrapper *w, ParmList *p) { SwigType_del_rvalue_reference(tvalue); tycode = SwigType_type(tvalue); if (tycode != T_USER) { - /* plain primitive type, we copy the the def value */ + /* plain primitive type, we copy the def value */ String *lstr = SwigType_lstr(tvalue, defname); defvalue = NewStringf("%s = %s", lstr, qvalue); Delete(lstr); @@ -1024,6 +1024,15 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas } } + if (!self && SwigType_isrvalue_reference(Getattr(n, "refqualifier"))) { + String *memory_header = NewString(""); + Setfile(memory_header, Getfile(n)); + Setline(memory_header, Getline(n)); + Swig_fragment_emit(memory_header); + self = NewString("std::move(*this)."); + Delete(memory_header); + } + call = Swig_cmethod_call(explicitcall_name ? explicitcall_name : name, p, self, explicit_qualifier, director_type); cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call); diff --git a/Source/Swig/error.c b/Source/Swig/error.c index 2c93cfb21..1dde06652 100644 --- a/Source/Swig/error.c +++ b/Source/Swig/error.c @@ -106,13 +106,16 @@ void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const c } if (warnall || wrn) { String *formatted_filename = format_filename(filename); + String *full_message = NewString(""); if (wnum) { - Printf(stderr, wrn_wnum_fmt, formatted_filename, line, wnum); + Printf(full_message, wrn_wnum_fmt, formatted_filename, line, wnum); } else { - Printf(stderr, wrn_nnum_fmt, formatted_filename, line); + Printf(full_message, wrn_nnum_fmt, formatted_filename, line); } - Printf(stderr, "%s", msg); + Printf(full_message, "%s", msg); + Printv(stderr, full_message, NIL); nwarning++; + Delete(full_message); Delete(formatted_filename); } Delete(out); @@ -128,6 +131,7 @@ void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const c void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ...) { va_list ap; String *formatted_filename = NULL; + String *full_message = NULL; if (silence) return; @@ -136,14 +140,17 @@ void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, .. va_start(ap, fmt); formatted_filename = format_filename(filename); + full_message = NewString(""); if (line > 0) { - Printf(stderr, err_line_fmt, formatted_filename, line); + Printf(full_message, err_line_fmt, formatted_filename, line); } else { - Printf(stderr, err_eof_fmt, formatted_filename); + Printf(full_message, err_eof_fmt, formatted_filename); } - vPrintf(stderr, fmt, ap); + vPrintf(full_message, fmt, ap); + Printv(stderr, full_message, NIL); va_end(ap); nerrors++; + Delete(full_message); Delete(formatted_filename); } diff --git a/Source/Swig/extend.c b/Source/Swig/extend.c index 30097b434..70355a245 100644 --- a/Source/Swig/extend.c +++ b/Source/Swig/extend.c @@ -106,10 +106,10 @@ void Swig_extend_append_previous(Node *cls, Node *am) { set_nextSibling(n,0); /* typemaps and fragments need to be prepended */ if (((Cmp(nodeType(n),"typemap") == 0) || (Cmp(nodeType(n),"fragment") == 0))) { - if (!pe) pe = new_node("extend"); + if (!pe) pe = Swig_cparse_new_node("extend"); appendChild(pe, n); } else { - if (!ae) ae = new_node("extend"); + if (!ae) ae = Swig_cparse_new_node("extend"); appendChild(ae, n); } n = ne; diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index 91f05c0a2..6b071185b 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -523,7 +523,7 @@ String *Swig_string_ucase(String *s) { /* We insert a underscore when: 1. Lower case char followed by upper case char getFoo > get_foo; getFOo > get_foo; GETFOO > getfoo - 2. Number proceded by char and not end of string + 2. Number preceded by char and not end of string get2D > get_2d; get22D > get_22d; GET2D > get_2d but: asFloat2 > as_float2 @@ -823,10 +823,11 @@ String *Swig_string_emangle(String *s) { /* ----------------------------------------------------------------------------- - * Swig_scopename_prefix() + * Swig_scopename_split() * - * Take a qualified name like "A::B::C" and return the scope name. - * In this case, "A::B". Returns NULL if there is no base. + * Take a qualified name like "A::B::C" and splits off the last name. + * In this case, returns "C" as last and "A::B" as prefix. + * Always returns non NULL for last, but prefix may be NULL if there is no prefix. * ----------------------------------------------------------------------------- */ void Swig_scopename_split(const String *s, String **rprefix, String **rlast) { @@ -882,6 +883,12 @@ void Swig_scopename_split(const String *s, String **rprefix, String **rlast) { } } +/* ----------------------------------------------------------------------------- + * Swig_scopename_prefix() + * + * Take a qualified name like "A::B::C" and return the scope name. + * In this case, "A::B". Returns NULL if there is no base. + * ----------------------------------------------------------------------------- */ String *Swig_scopename_prefix(const String *s) { char *tmp = Char(s); @@ -1067,6 +1074,31 @@ String *Swig_scopename_suffix(const String *s) { } } +/* ----------------------------------------------------------------------------- + * Swig_scopename_tolist() + * + * Take a qualified scope name like "A::B::C" and convert it to a list. + * In this case, return a list of 3 elements "A", "B", "C". + * Returns an empty list if the input is empty. + * ----------------------------------------------------------------------------- */ + +List *Swig_scopename_tolist(const String *s) { + List *scopes = NewList(); + String *name = Len(s) == 0 ? 0 : NewString(s); + + while (name) { + String *last = 0; + String *prefix = 0; + Swig_scopename_split(name, &prefix, &last); + Insert(scopes, 0, last); + Delete(last); + Delete(name); + name = prefix; + } + Delete(name); + return scopes; +} + /* ----------------------------------------------------------------------------- * Swig_scopename_check() * @@ -1117,19 +1149,17 @@ int Swig_scopename_check(const String *s) { * * Printf(stderr,"%(command:sed 's/[a-z]/\U\\1/' <<<)s","hello") -> Hello * ----------------------------------------------------------------------------- */ -#if defined(HAVE_POPEN) -# if defined(_MSC_VER) -# define popen _popen -# define pclose _pclose -# else -extern FILE *popen(const char *command, const char *type); -extern int pclose(FILE *stream); +#if defined(_MSC_VER) +# define popen _popen +# define pclose _pclose +# if !defined(HAVE_POPEN) +# define HAVE_POPEN 1 # endif #else -# if defined(_MSC_VER) -# define HAVE_POPEN 1 -# define popen _popen -# define pclose _pclose +# if !defined(_WIN32) +/* These Posix functions are not ISO C and so are not always defined in stdio.h */ +extern FILE *popen(const char *command, const char *type); +extern int pclose(FILE *stream); # endif #endif @@ -1208,7 +1238,7 @@ String *Swig_string_rstrip(String *s) { String *suffix = NewStringf(fmt, cs+1); int suffix_len = Len(suffix); if (0 == Strncmp(cs+len-suffix_len, suffix, suffix_len)) { - int copy_len = len-suffix_len-(ce+1-cs); + int copy_len = len-suffix_len-(int)(ce+1-cs); ns = NewStringWithSize(ce+1, copy_len); } else { ns = NewString(ce+1); @@ -1454,6 +1484,17 @@ String *Swig_pcre_version(void) { #endif +/* ------------------------------------------------------------ + * Swig_is_generated_overload() + * Check if the function is an automatically generated + * overload created because a method has default parameters. + * ------------------------------------------------------------ */ +int Swig_is_generated_overload(Node *n) { + Node *base_method = Getattr(n, "sym:overloaded"); + Node *default_args = Getattr(n, "defaultargs"); + return ((base_method != NULL) && (default_args != NULL) && (base_method == default_args)); +} + /* ----------------------------------------------------------------------------- * Swig_init() * diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index c7f187177..1b6c963e7 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -404,7 +404,17 @@ DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType } Delete(cls); } - /* A template-based class lookup, check name first */ + /* Lookup a name within a templated-based class */ + if (!rn) { + String *t_name = SwigType_istemplate_templateprefix(prefix); + if (t_name) { + Clear(tname); + Printf(tname, "%s::%s", t_name, name); + rn = name_object_get(namehash, tname, decl, ncdecl); + Delete(t_name); + } + } + /* Lookup a template-based name within a class */ if (!rn) { String *t_name = SwigType_istemplate_templateprefix(name); if (t_name) @@ -429,8 +439,8 @@ DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType rn = name_object_get(namehash, name, decl, ncdecl); } if (!rn && Swig_scopename_check(name)) { - String *nprefix = NewStringEmpty(); - String *nlast = NewStringEmpty(); + String *nprefix = 0; + String *nlast = 0; Swig_scopename_split(name, &nprefix, &nlast); rn = name_object_get(namehash, nlast, decl, ncdecl); Delete(nlast); @@ -569,8 +579,8 @@ void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *d if (name && SwigType_istemplate(name)) { String *nodetype = nodeType(node); if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) { - String *nprefix = NewStringEmpty(); - String *nlast = NewStringEmpty(); + String *nprefix = 0; + String *nlast = 0; String *tprefix; Swig_scopename_split(name, &nprefix, &nlast); tprefix = SwigType_templateprefix(nlast); @@ -789,6 +799,8 @@ static int need_name_warning(Node *n) { need = 0; } else if (Getattr(n, "templatetype")) { need = 0; + } else if (GetFlag(n, "parsing_template_declaration")) { + need = 0; } return need; } @@ -1043,7 +1055,7 @@ static void name_nameobj_add(Hash *name_hash, List *name_list, String *prefix, S Setattr(nameobj, "decl", decl); if (nname && Len(nname)) Setattr(nameobj, "targetname", nname); - /* put the new nameobj at the beginnig of the list, such that the + /* put the new nameobj at the beginning of the list, such that the last inserted rule take precedence */ Insert(name_list, 0, nameobj); } else { @@ -1365,12 +1377,15 @@ void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *ne } -/* Create a name applying rename/namewarn if needed */ -static String *apply_rename(String *newname, int fullname, String *prefix, String *name) { +/* Create a name for the given node applying rename/namewarn if needed */ +static String *apply_rename(Node* n, String *newname, int fullname, String *prefix, String *name) { String *result = 0; if (newname && Len(newname)) { if (Strcmp(newname, "$ignore") == 0) { - result = Copy(newname); + /* $ignore doesn't apply to parameters and while it's rare to explicitly write %ignore directives for them they could be caught by a wildcard ignore using + regex match, just ignore the attempt to ignore them in this case */ + if (!Equal(nodeType(n), "parm")) + result = Copy(newname); } else { char *cnewname = Char(newname); if (cnewname) { @@ -1419,8 +1434,8 @@ String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname, if (name && n && SwigType_istemplate(name)) { String *nodetype = nodeType(n); if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) { - String *nprefix = NewStringEmpty(); - String *nlast = NewStringEmpty(); + String *nprefix = 0; + String *nlast = 0; String *tprefix; Swig_scopename_split(name, &nprefix, &nlast); tprefix = SwigType_templateprefix(nlast); @@ -1468,7 +1483,7 @@ String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname, if (rn) { String *newname = Getattr(rn, "name"); int fullname = GetFlag(rn, "fullname"); - result = apply_rename(newname, fullname, prefix, name); + result = apply_rename(n, newname, fullname, prefix, name); } if (result && !Equal(result, name)) { /* operators in C++ allow aliases, we look for them */ @@ -1492,13 +1507,19 @@ String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname, int fullname = GetFlag(wrn, "fullname"); if (result) Delete(result); - result = apply_rename(rename, fullname, prefix, name); + result = apply_rename(n, rename, fullname, prefix, name); if ((msg) && (Len(msg))) { if (!Getmeta(nname, "already_warned")) { if (n) { - SWIG_WARN_NODE_BEGIN(n); - Swig_warning(0, Getfile(n), Getline(n), "%s\n", msg); - SWIG_WARN_NODE_END(n); + /* Parameter renaming is not fully implemented. Mainly because there is no C/C++ syntax to + * for %rename to fully qualify a function's parameter name from outside the function. Hence it + * is not possible to implemented targetted warning suppression on one parameter in one function. */ + int suppress_parameter_rename_warning = Equal(nodeType(n), "parm"); + if (!suppress_parameter_rename_warning) { + SWIG_WARN_NODE_BEGIN(n); + Swig_warning(0, Getfile(n), Getline(n), "%s\n", msg); + SWIG_WARN_NODE_END(n); + } } else { Swig_warning(0, Getfile(name), Getline(name), "%s\n", msg); } @@ -1638,12 +1659,13 @@ String *Swig_name_str(Node *n) { if (SwigType_istemplate(name)) { String *nodetype = nodeType(n); if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) { - String *nprefix = NewStringEmpty(); - String *nlast = NewStringEmpty(); + String *nprefix = 0; + String *nlast = 0; String *tprefix; Swig_scopename_split(name, &nprefix, &nlast); tprefix = SwigType_templateprefix(nlast); Delete(nlast); + Delete(nprefix); Delete(name); name = tprefix; } @@ -1669,6 +1691,7 @@ String *Swig_name_str(Node *n) { * "MyNameSpace::MyTemplate::~MyTemplate()" * "MyNameSpace::ABC::ABC(int,double)" * "MyNameSpace::ABC::constmethod(int) const" + * "MyNameSpace::ABC::refqualifiermethod(int) const &" * "MyNameSpace::ABC::variablename" * * ----------------------------------------------------------------------------- */ @@ -1678,11 +1701,22 @@ String *Swig_name_decl(Node *n) { String *decl; qname = Swig_name_str(n); + decl = NewStringf("%s", qname); - if (checkAttribute(n, "kind", "variable")) - decl = NewStringf("%s", qname); - else - decl = NewStringf("%s(%s)%s", qname, ParmList_errorstr(Getattr(n, "parms")), SwigType_isconst(Getattr(n, "decl")) ? " const" : ""); + if (!checkAttribute(n, "kind", "variable")) { + String *d = Getattr(n, "decl"); + Printv(decl, "(", ParmList_errorstr(Getattr(n, "parms")), ")", NIL); + if (SwigType_isfunction(d)) { + SwigType *decl_temp = Copy(d); + SwigType *qualifiers = SwigType_pop_function_qualifiers(decl_temp); + if (qualifiers) { + String *qualifiers_string = SwigType_str(qualifiers, 0); + Printv(decl, " ", qualifiers_string, NIL); + Delete(qualifiers_string); + } + Delete(decl_temp); + } + } Delete(qname); diff --git a/Source/Swig/parms.c b/Source/Swig/parms.c index bec1e63fa..3e832c361 100644 --- a/Source/Swig/parms.c +++ b/Source/Swig/parms.c @@ -254,3 +254,19 @@ int ParmList_has_defaultargs(ParmList *p) { } return 0; } + +/* --------------------------------------------------------------------- + * ParmList_has_varargs() + * + * Returns 1 if the parameter list passed in has varargs. + * Otherwise returns 0. + * ---------------------------------------------------------------------- */ + +int ParmList_has_varargs(ParmList *p) { + Parm *lp = 0; + while (p) { + lp = p; + p = nextSibling(p); + } + return lp ? SwigType_isvarargs(Getattr(lp, "type")) : 0; +} diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c index 227a1d00c..908bc747f 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -749,11 +749,18 @@ static int look(Scanner *s) { } if (Strcmp( str_delimiter, end_delimiter )==0) { - Delete( end_delimiter ); /* Correct end delimiter )XXXX" occured */ + int len = Len(s->text); + Delslice(s->text, len - 2 - Len(str_delimiter), len); /* Delete ending )XXXX" */ + Delslice(s->text, 0, Len(str_delimiter) + 1); /* Delete starting XXXX( */ + Delete( end_delimiter ); /* Correct end delimiter )XXXX" occurred */ Delete( str_delimiter ); str_delimiter = 0; return SWIG_TOKEN_STRING; - } else { /* Incorrect end delimiter occured */ + } else { /* Incorrect end delimiter occurred */ + if (c == 0) { + Swig_error(cparse_file, cparse_start_line, "Unterminated raw string, started with R\"%s( is not terminated by )%s\"\n", str_delimiter, str_delimiter); + return SWIG_TOKEN_ERROR; + } retract( s, i ); Delete( end_delimiter ); } @@ -931,10 +938,14 @@ static int look(Scanner *s) { retract(s, 1); state = 1000; } + else if (c == '\'') { /* Definitely u, U or L char */ + retract(s, 1); + state = 77; + } else if (c == 'R') { /* Possibly CUSTOM DELIMITER u, U, L string */ state = 73; } - else if (c == '8') { /* Possibly u8 string */ + else if (c == '8') { /* Possibly u8 string/char */ state = 71; } else { @@ -954,7 +965,7 @@ static int look(Scanner *s) { } break; - case 71: /* Possibly u8 string */ + case 71: /* Possibly u8 string/char */ if ((c = nextchar(s)) == 0) { state = 76; } @@ -962,6 +973,10 @@ static int look(Scanner *s) { retract(s, 1); /* Definitely u8 string */ state = 1000; } + else if (c=='\'') { + retract(s, 1); /* Definitely u8 char */ + state = 77; + } else if (c=='R') { state = 74; /* Possibly CUSTOM DELIMITER u8 string */ } @@ -1114,27 +1129,29 @@ static int look(Scanner *s) { break; case 82: if ((c = nextchar(s)) == 0) { - retract(s, 1); - return SWIG_TOKEN_INT; + Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n"); + return SWIG_TOKEN_ERROR; } if ((isdigit(c)) || (c == '-') || (c == '+')) state = 86; else { retract(s, 2); - return (SWIG_TOKEN_INT); + Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n"); + return SWIG_TOKEN_ERROR; } break; case 820: /* Like case 82, but we've seen a decimal point. */ if ((c = nextchar(s)) == 0) { - retract(s, 1); - return SWIG_TOKEN_DOUBLE; + Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n"); + return SWIG_TOKEN_ERROR; } if ((isdigit(c)) || (c == '-') || (c == '+')) state = 86; else { retract(s, 2); - return (SWIG_TOKEN_DOUBLE); + Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n"); + return SWIG_TOKEN_ERROR; } break; case 83: @@ -1143,8 +1160,12 @@ static int look(Scanner *s) { return SWIG_TOKEN_INT; if (isdigit(c)) state = 84; + else if ((c == 'e') || (c == 'E')) + state = 82; else if ((c == 'x') || (c == 'X')) state = 85; + else if ((c == 'b') || (c == 'B')) + state = 850; else if (c == '.') state = 81; else if ((c == 'l') || (c == 'L')) { @@ -1162,6 +1183,10 @@ static int look(Scanner *s) { return SWIG_TOKEN_INT; if (isdigit(c)) state = 84; + else if (c == '.') + state = 81; + else if ((c == 'e') || (c == 'E')) + state = 82; else if ((c == 'l') || (c == 'L')) { state = 87; } else if ((c == 'u') || (c == 'U')) { @@ -1177,6 +1202,10 @@ static int look(Scanner *s) { return SWIG_TOKEN_INT; if (isxdigit(c)) state = 85; + else if (c == '.') /* hexadecimal float */ + state = 860; + else if ((c == 'p') || (c == 'P')) /* hexadecimal float */ + state = 820; else if ((c == 'l') || (c == 'L')) { state = 87; } else if ((c == 'u') || (c == 'U')) { @@ -1186,7 +1215,37 @@ static int look(Scanner *s) { return SWIG_TOKEN_INT; } break; - + case 850: + /* This is a binary number */ + if ((c = nextchar(s)) == 0) + return SWIG_TOKEN_INT; + if ((c == '0') || (c == '1')) + state = 850; + else if ((c == 'l') || (c == 'L')) { + state = 87; + } else if ((c == 'u') || (c == 'U')) { + state = 88; + } else { + retract(s, 1); + return SWIG_TOKEN_INT; + } + break; + case 860: + /* hexadecimal float */ + if ((c = nextchar(s)) == 0) { + Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n"); + return SWIG_TOKEN_ERROR; + } + if (isxdigit(c)) + state = 860; + else if ((c == 'p') || (c == 'P')) + state = 820; + else { + retract(s, 2); + Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n"); + return SWIG_TOKEN_ERROR; + } + break; case 86: /* Rest of floating point number */ diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index a57222745..66518f50c 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -44,8 +44,8 @@ * 'z.' = Rvalue reference (&&) * 'a(n).' = Array of size n [n] * 'f(..,..).' = Function with arguments (args) - * 'q(str).' = Qualifier (such as const or volatile) (const, volatile) - * 'm(qual).' = Pointer to member (qual::*) + * 'q(str).' = Qualifier, such as const or volatile (cv-qualifier) + * 'm(cls).' = Pointer to member (cls::*) * * The encoding follows the order that you might describe a type in words. * For example "p.a(200).int" is "A pointer to array of int's" and @@ -62,6 +62,22 @@ * * Replace(t,"q(const).","",DOH_REPLACE_ANY) * + * More examples: + * + * String Encoding C++ Example + * --------------- ----------- + * p.f(bool).r.q(const).long const long & (*)(bool) + * m(Funcs).q(const).f(bool).long long (Funcs::*)(bool) const + * r.q(const).m(Funcs).f(int).long long (Funcs::*const &)(int) + * m(Funcs).z.q(const).f(bool).long long (Funcs::*)(bool) const && + * + * Function decl examples: + * + * f(bool). long a(bool); + * r.f(bool). long b(bool) &; + * z.f(bool). long c(bool) &&; + * z.q(const).f(bool). long d(bool) const &&; + * * For the most part, this module tries to minimize the use of special * characters (*, [, <, etc...) in its type encoding. One reason for this * is that SWIG might be extended to encode data in formats such as XML @@ -372,7 +388,7 @@ SwigType *SwigType_default_create(const SwigType *ty) { * and is very close to the type deduction used in partial template class * specialization matching in that the most specialized type is always chosen. * SWIGTYPE is used as the generic type. The basic idea is to repeatedly call - * this function to find a deduced type unless until nothing matches. + * this function to find a deduced type until nothing matches. * * The type t must have already been converted to the default type via a call to * SwigType_default_create() before calling this function. @@ -528,6 +544,7 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) { String *element = 0; String *nextelement; String *forwardelement; + SwigType *member_function_qualifiers = 0; List *elements; int nelements, i; @@ -560,11 +577,13 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) { forwardelement = 0; } if (SwigType_isqualifier(element)) { - DOH *q = 0; - q = SwigType_parm(element); - Insert(result, 0, " "); - Insert(result, 0, q); - Delete(q); + if (!member_function_qualifiers) { + DOH *q = 0; + q = SwigType_parm(element); + Insert(result, 0, " "); + Insert(result, 0, q); + Delete(q); + } } else if (SwigType_ispointer(element)) { Insert(result, 0, "*"); if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) { @@ -580,16 +599,28 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) { Insert(result, 0, "("); Append(result, ")"); } + { + String *next3elements = NewStringEmpty(); + int j; + for (j = i + 1; j < i + 4 && j < nelements; j++) { + Append(next3elements, Getitem(elements, j)); + } + if (SwigType_isfunction(next3elements)) + member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements); + Delete(next3elements); + } Delete(q); } else if (SwigType_isreference(element)) { - Insert(result, 0, "&"); + if (!member_function_qualifiers) + Insert(result, 0, "&"); if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) { Insert(result, 0, "("); Append(result, ")"); } } else if (SwigType_isrvalue_reference(element)) { - Insert(result, 0, "&&"); - if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) { + if (!member_function_qualifiers) + Insert(result, 0, "&&"); + if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) { Insert(result, 0, "("); Append(result, ")"); } @@ -613,6 +644,14 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) { Append(result, ","); } Append(result, ")"); + if (member_function_qualifiers) { + String *p = SwigType_str(member_function_qualifiers, 0); + Append(result, " "); + Append(result, p); + Delete(p); + Delete(member_function_qualifiers); + member_function_qualifiers = 0; + } Delete(parms); } else { if (strcmp(Char(element), "v(...)") == 0) { @@ -645,6 +684,7 @@ SwigType *SwigType_ltype(const SwigType *s) { int nelements, i; int firstarray = 1; int notypeconv = 0; + int ignore_member_function_qualifiers = 0; result = NewStringEmpty(); tc = Copy(s); @@ -671,6 +711,7 @@ SwigType *SwigType_ltype(const SwigType *s) { tc = td; } } + elements = SwigType_split(tc); nelements = Len(elements); @@ -680,14 +721,33 @@ SwigType *SwigType_ltype(const SwigType *s) { /* when we see a function, we need to preserve the following types */ if (SwigType_isfunction(element)) { notypeconv = 1; + ignore_member_function_qualifiers = 0; } - if (SwigType_isqualifier(element)) { - /* Do nothing. Ignore */ + if (ignore_member_function_qualifiers) { + /* cv-qualifiers and ref-qualifiers up until the f() element have already been added */ + } else if (SwigType_isqualifier(element)) { + /* swallow cv-qualifiers */ } else if (SwigType_ispointer(element)) { Append(result, element); firstarray = 0; } else if (SwigType_ismemberpointer(element)) { Append(result, element); + { + String *next3elements = NewStringEmpty(); + int j; + for (j = i + 1; j < i + 4 && j < nelements; j++) { + Append(next3elements, Getitem(elements, j)); + } + if (SwigType_isfunction(next3elements)) { + SwigType *member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements); + /* compilers won't let us cast from a member function without qualifiers to one with qualifiers, so the qualifiers are kept in the ltype */ + if (member_function_qualifiers) + Append(result, member_function_qualifiers); + Delete(member_function_qualifiers); + ignore_member_function_qualifiers = 1; + } + Delete(next3elements); + } firstarray = 0; } else if (SwigType_isreference(element)) { if (notypeconv) { @@ -727,13 +787,14 @@ SwigType *SwigType_ltype(const SwigType *s) { } /* ----------------------------------------------------------------------------- - * SwigType_lstr(DOH *s, DOH *id) + * SwigType_lstr() * * Produces a type-string that is suitable as a lvalue in an expression. * That is, a type that can be freely assigned a value without violating * any C assignment rules. * * - Qualifiers such as 'const' and 'volatile' are stripped. + * Except for member function cv-qualifiers and ref-qualifiers. * - Arrays are converted into a *single* pointer (i.e., * double [][] becomes double *). * - References are converted into a pointer. @@ -763,6 +824,7 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) { String *element = 0; String *nextelement; String *forwardelement; + String *member_function_qualifiers = 0; SwigType *td, *tc = 0; const SwigType *rs; List *elements; @@ -777,7 +839,10 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) { if (SwigType_isconst(s)) { tc = Copy(s); Delete(SwigType_pop(tc)); - rs = tc; + if (SwigType_ismemberpointer(tc)) + rs = s; + else + rs = tc; } else { rs = s; } @@ -816,12 +881,14 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) { forwardelement = 0; } if (SwigType_isqualifier(element)) { - DOH *q = 0; - q = SwigType_parm(element); - Insert(result, 0, " "); - Insert(result, 0, q); - Delete(q); - clear = 0; + if (!member_function_qualifiers) { + DOH *q = 0; + q = SwigType_parm(element); + Insert(result, 0, " "); + Insert(result, 0, q); + Delete(q); + clear = 0; + } } else if (SwigType_ispointer(element)) { Insert(result, 0, "*"); if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) { @@ -834,28 +901,42 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) { Insert(result, 0, "::*"); q = SwigType_parm(element); Insert(result, 0, q); - Delete(q); if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) { Insert(result, 0, "("); Append(result, ")"); } + { + String *next3elements = NewStringEmpty(); + int j; + for (j = i + 1; j < i + 4 && j < nelements; j++) { + Append(next3elements, Getitem(elements, j)); + } + if (SwigType_isfunction(next3elements)) + member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements); + Delete(next3elements); + } firstarray = 0; + Delete(q); } else if (SwigType_isreference(element)) { - Insert(result, 0, "&"); + if (!member_function_qualifiers) { + Insert(result, 0, "&"); + if (!isfunction) + isreference = 1; + } if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) { Insert(result, 0, "("); Append(result, ")"); } - if (!isfunction) - isreference = 1; } else if (SwigType_isrvalue_reference(element)) { - Insert(result, 0, "&&"); + if (!member_function_qualifiers) { + Insert(result, 0, "&&"); + if (!isfunction) + isreference = 1; + } if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) { Insert(result, 0, "("); Append(result, ")"); } - if (!isfunction) - isreference = 1; clear = 0; } else if (SwigType_isarray(element)) { DOH *size; @@ -885,6 +966,15 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) { } Append(result, ")"); Delete(parms); + if (member_function_qualifiers) { + String *p = SwigType_str(member_function_qualifiers, 0); + Append(result, " "); + Append(result, p); + Delete(p); + Delete(member_function_qualifiers); + member_function_qualifiers = 0; + clear = 0; + } isfunction = 1; } else { String *bs = SwigType_namestr(element); @@ -1220,6 +1310,7 @@ void SwigType_typename_replace(SwigType *t, String *pat, String *rep) { Putc(',', nt); } tsuffix = SwigType_templatesuffix(e); + SwigType_typename_replace(tsuffix, pat, rep); Printf(nt, ")>%s", tsuffix); Delete(tsuffix); Clear(e); @@ -1228,13 +1319,24 @@ void SwigType_typename_replace(SwigType *t, String *pat, String *rep) { Delete(tparms); } } else if (Swig_scopename_check(e)) { - String *first, *rest; - first = Swig_scopename_first(e); - rest = Swig_scopename_suffix(e); - SwigType_typename_replace(rest, pat, rep); - SwigType_typename_replace(first, pat, rep); + String *first = 0; + String *rest = 0; + Swig_scopename_split(e, &first, &rest); + + /* Swig_scopename_split doesn't handle :: prefix very well ... could do with a rework */ + if (Strncmp(rest, "::", 2) == 0) { + String *tmp = NewString(Char(rest) + 2); + Clear(rest); + Printv(rest, tmp, NIL); + Delete(tmp); + assert(!first); + } + Clear(e); - Printv(e, first, "::", rest, NIL); + if (first) + SwigType_typename_replace(first, pat, rep); + SwigType_typename_replace(rest, pat, rep); + Printv(e, first ? first : "", "::", rest, NIL); Delete(first); Delete(rest); } diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 35a67640f..1acd32d5d 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -136,6 +136,7 @@ extern "C" { extern SwigType *SwigType_add_function(SwigType *t, ParmList *parms); extern SwigType *SwigType_add_template(SwigType *t, ParmList *parms); extern SwigType *SwigType_pop_function(SwigType *t); + extern SwigType *SwigType_pop_function_qualifiers(SwigType *t); extern ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node); extern List *SwigType_split(const SwigType *t); extern String *SwigType_pop(SwigType *t); @@ -187,7 +188,7 @@ extern "C" { extern SwigType *SwigType_remove_global_scope_prefix(const SwigType *t); extern SwigType *SwigType_alttype(const SwigType *t, int ltmap); -/* --- Type-system managment --- */ +/* --- Type-system management --- */ extern void SwigType_typesystem_init(void); extern int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name); extern int SwigType_typedef_class(const_String_or_char_ptr name); @@ -326,6 +327,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern String *Swig_scopename_last(const String *s); extern String *Swig_scopename_first(const String *s); extern String *Swig_scopename_suffix(const String *s); + extern List *Swig_scopename_tolist(const String *s); extern int Swig_scopename_check(const String *s); extern String *Swig_string_lower(String *s); extern String *Swig_string_upper(String *s); @@ -333,7 +335,9 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern void Swig_offset_string(String *s, int number); extern String *Swig_pcre_version(void); extern void Swig_init(void); + extern int Swig_value_wrapper_mode(int mode); + extern int Swig_is_generated_overload(Node *n); typedef enum { EMF_STANDARD, EMF_MICROSOFT } ErrorMessageFormat; @@ -400,6 +404,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *pattern); extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat); extern void Swig_typemap_clear_apply(ParmList *pattern); + extern void Swig_typemap_replace_embedded_typemap(String *s, Node *file_line_node); extern void Swig_typemap_debug(void); extern void Swig_typemap_search_debug_set(void); extern void Swig_typemap_used_debug_set(void); diff --git a/Source/Swig/swigparm.h b/Source/Swig/swigparm.h index 368b4d26b..7b27df5f6 100644 --- a/Source/Swig/swigparm.h +++ b/Source/Swig/swigparm.h @@ -24,6 +24,7 @@ extern ParmList *CopyParmListMax(ParmList *, int count); extern int ParmList_len(ParmList *); extern int ParmList_numrequired(ParmList *); extern int ParmList_has_defaultargs(ParmList *p); +extern int ParmList_has_varargs(ParmList *p); /* Output functions */ extern String *ParmList_str(ParmList *); diff --git a/Source/Swig/swigscan.h b/Source/Swig/swigscan.h index 6a181f86f..740a93610 100644 --- a/Source/Swig/swigscan.h +++ b/Source/Swig/swigscan.h @@ -50,7 +50,7 @@ extern void Scanner_locator(Scanner *, String *loc); #define SWIG_TOKEN_COLON 12 /* : */ #define SWIG_TOKEN_DCOLON 13 /* :: */ #define SWIG_TOKEN_DCOLONSTAR 14 /* ::* */ -#define SWIG_TOKEN_ID 15 /* identifer */ +#define SWIG_TOKEN_ID 15 /* identifier */ #define SWIG_TOKEN_FLOAT 16 /* 3.1415F */ #define SWIG_TOKEN_DOUBLE 17 /* 3.1415 */ #define SWIG_TOKEN_INT 18 /* 314 */ diff --git a/Source/Swig/symbol.c b/Source/Swig/symbol.c index d72451a14..aacaf24be 100644 --- a/Source/Swig/symbol.c +++ b/Source/Swig/symbol.c @@ -210,9 +210,10 @@ void Swig_symbol_print_tables_summary(void) { * symbol_print_symbols() * ----------------------------------------------------------------------------- */ -static void symbol_print_symbols(const char *symboltabletype) { +static void symbol_print_symbols(const char *symboltabletype, const char *nextSibling) { Node *table = symtabs; Iterator ki = First(table); + int show_pointers = 0; while (ki.key) { String *k = ki.key; Printf(stdout, "===================================================\n"); @@ -222,10 +223,20 @@ static void symbol_print_symbols(const char *symboltabletype) { Iterator it = First(symtab); while (it.key) { String *symname = it.key; - Printf(stdout, " %s (%s)\n", symname, nodeType(it.item)); - /* - Printf(stdout, " %s - %p (%s)\n", symname, it.item, Getattr(it.item, "name")); - */ + Printf(stdout, " %s (%s)", symname, nodeType(it.item)); + if (show_pointers) + Printf(stdout, " %p", it.item); + Printf(stdout, "\n"); + { + Node *sibling = Getattr(it.item, nextSibling); + while (sibling) { + Printf(stdout, " %s (%s)", symname, nodeType(sibling)); + if (show_pointers) + Printf(stdout, " %p", sibling); + Printf(stdout, "\n"); + sibling = Getattr(sibling, nextSibling); + } + } it = Next(it); } } @@ -241,7 +252,7 @@ static void symbol_print_symbols(const char *symboltabletype) { void Swig_symbol_print_symbols(void) { Printf(stdout, "SYMBOLS start =======================================\n"); - symbol_print_symbols("symtab"); + symbol_print_symbols("symtab", "sym:nextSibling"); Printf(stdout, "SYMBOLS finish =======================================\n"); } @@ -253,7 +264,7 @@ void Swig_symbol_print_symbols(void) { void Swig_symbol_print_csymbols(void) { Printf(stdout, "CSYMBOLS start =======================================\n"); - symbol_print_symbols("csymtab"); + symbol_print_symbols("csymtab", "csym:nextSibling"); Printf(stdout, "CSYMBOLS finish =======================================\n"); } @@ -518,7 +529,6 @@ void Swig_symbol_inherit(Symtab *s) { void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) { Node *append = 0; - Node *cn; /* There are a few options for weak symbols. A "weak" symbol is any symbol that can be replaced by another symbol in the C symbol @@ -600,7 +610,7 @@ void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) { Setattr(ccurrent, name, n); } - /* Multiple entries in the C symbol table. We append to to the symbol table */ + /* Multiple entries in the C symbol table. We append to the symbol table */ if (append) { Node *fn, *pn = 0; cn = Getattr(ccurrent, name); @@ -691,7 +701,7 @@ void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) { * ----------------------------------------------------------------------------- */ Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) { - Hash *c, *cn, *cl = 0; + Hash *c, *cl = 0; SwigType *decl, *ndecl; String *cstorage, *nstorage; int nt = 0, ct = 0; @@ -757,10 +767,9 @@ Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) { (1) A conflict between a class/enum and a typedef declaration is okay. In this case, the symbol table entry is set to the class/enum declaration itself, not the typedef. - (2) A conflict between namespaces is okay--namespaces are open - (3) Otherwise, overloading is only allowed for functions + (4) This special case is okay: a class template instantiated with same name as the template's name */ /* Check for namespaces */ @@ -778,6 +787,25 @@ Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) { Setattr(n, "sym:previousSibling", pcl); return n; } + + /* Special case: class template instantiated with same name as the template's name eg: %template(X) X; */ + if (Equal(nodeType(c), "template")) { + String *nt1 = Getattr(c, "templatetype"); + String *nt2 = nodeType(n); + if (Equal(nt1, "class") && Equal(nt1, nt2)) { + if (Getattr(n, "template")) { + /* Finally check that another %template with same name doesn't already exist */ + if (!Getattr(c, "sym:nextSibling")) { + Setattr(c, "sym:nextSibling", n); + Setattr(n, "sym:symtab", current_symtab); + Setattr(n, "sym:name", symname); + Setattr(n, "sym:previousSibling", c); + return n; + } + } + } + } + if (Getattr(n, "allows_typedef")) nt = 1; if (Getattr(c, "allows_typedef")) @@ -858,7 +886,7 @@ Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) { String *nt = Getattr(n, "nodeType"); int n_template = Equal(nt, "template") && Checkattr(n, "templatetype", "cdecl"); int n_plain_cdecl = Equal(nt, "cdecl"); - cn = c; + Node *cn = c; pn = 0; while (cn) { decl = Getattr(cn, "decl"); @@ -1011,8 +1039,8 @@ static Node *symbol_lookup_qualified(const_String_or_char_ptr name, Symtab *symt return 0; if (!prefix) { Node *n; - String *bname; - String *prefix; + String *bname = 0; + String *prefix = 0; Swig_scopename_split(name, &prefix, &bname); n = symbol_lookup_qualified(bname, symtab, prefix, local, checkfunc); Delete(bname); @@ -1907,19 +1935,37 @@ SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope) { int len = Len(elements); int i; #ifdef SWIG_TEMPLATE_DEFTYPE_CACHE - static Hash *deftype_cache = 0; - String *scopetype = tscope ? NewStringf("%s::%s", Getattr(tscope, "name"), type) + static Hash *s_cache = 0; + Hash *scope_cache; + /* The lookup depends on the current scope and potential namespace qualification. + Looking up x in namespace y is not the same as looking up x::y in outer scope. + -> we use a 2-level hash: first scope and then symbol. */ + String *scope_name = tscope + ? Swig_symbol_qualifiedscopename(tscope) + : Swig_symbol_qualifiedscopename(current_symtab); + String *type_name = tscope + ? NewStringf("%s::%s", Getattr(tscope, "name"), type) : NewStringf("%s::%s", Swig_symbol_getscopename(), type); - if (!deftype_cache) { - deftype_cache = NewHash(); + if (!scope_name) scope_name = NewString("::"); + if (!s_cache) { + s_cache = NewHash(); } - if (scopetype) { - String *cres = Getattr(deftype_cache, scopetype); + scope_cache = Getattr(s_cache, scope_name); + if (scope_cache) { + String *cres = Getattr(scope_cache, type_name); if (cres) { Append(result, cres); - Delete(scopetype); +#ifdef SWIG_DEBUG + Printf(stderr, "cached deftype %s(%s) -> %s\n", type, scope_name, result); +#endif + Delete(type_name); + Delete(scope_name); return result; } + } else { + scope_cache = NewHash(); + Setattr(s_cache, scope_name, scope_cache); + Delete(scope_name); } #endif @@ -2019,8 +2065,8 @@ SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope) { } Delete(elements); #ifdef SWIG_TEMPLATE_DEFTYPE_CACHE - Setattr(deftype_cache, scopetype, result); - Delete(scopetype); + Setattr(scope_cache, type_name, result); + Delete(type_name); #endif return result; diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c index 78c04dc90..46571fc09 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -75,9 +75,11 @@ void Swig_print_node(Node *obj) { if ((Cmp(k, "nodeType") == 0) || (Cmp(k, "firstChild") == 0) || (Cmp(k, "lastChild") == 0) || (Cmp(k, "parentNode") == 0) || (Cmp(k, "nextSibling") == 0) || (Cmp(k, "previousSibling") == 0) || (*(Char(k)) == '$')) { /* Do nothing */ - } else if (Cmp(k, "parms") == 0 || Cmp(k, "wrap:parms") == 0) { + } else if (Cmp(k, "kwargs") == 0 || Cmp(k, "parms") == 0 || Cmp(k, "wrap:parms") == 0 || + Cmp(k, "pattern") == 0 || Cmp(k, "templateparms") == 0 || Cmp(k, "throws") == 0) { print_indent(2); - Printf(stdout, "%-12s - %s\n", k, ParmList_str_defaultargs(Getattr(obj, k))); + /* Differentiate parameter lists by displaying within single quotes */ + Printf(stdout, "%-12s - \'%s\'\n", k, ParmList_str_defaultargs(Getattr(obj, k))); } else { DOH *o; const char *trunc = ""; diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index ab2a8c0df..c0f5397c1 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -61,13 +61,44 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper static Hash *typemaps; +/* ----------------------------------------------------------------------------- + * typemap_identifier_fix() + * + * Create a type that can be used as a hash key lookup independent of the various + * ways a template parameter list can be defined. This is achieved by fully + * resolving the template parameters. + * + * This is a copy and modification of feature_identifier_fix in parser.y. + * ----------------------------------------------------------------------------- */ + +static SwigType *typemap_identifier_fix(const SwigType *s) { + String *tp = SwigType_istemplate_templateprefix(s); + if (tp) { + String *ts, *ta, *tq, *tr; + ts = SwigType_templatesuffix(s); + ta = SwigType_templateargs(s); + tq = Swig_symbol_type_qualify(ta, 0); + tr = SwigType_typedef_resolve_all(ta); + Append(tp,tr); + Append(tp,ts); + Delete(ts); + Delete(ta); + Delete(tq); + Delete(tr); + return tp; + } else { + return NewString(s); + } +} + static Hash *get_typemap(const SwigType *type) { Hash *tm = 0; SwigType *dtype = 0; SwigType *hashtype; if (SwigType_istemplate(type)) { - String *ty = Swig_symbol_template_deftype(type, 0); + SwigType *rty = typemap_identifier_fix(type); + String *ty = Swig_symbol_template_deftype(rty, 0); dtype = Swig_symbol_type_qualify(ty, 0); type = dtype; Delete(ty); @@ -88,7 +119,7 @@ static void set_typemap(const SwigType *type, Hash **tmhash) { Hash *new_tm = 0; assert(*tmhash == 0); if (SwigType_istemplate(type)) { - SwigType *rty = SwigType_typedef_resolve_all(type); + SwigType *rty = typemap_identifier_fix(type); String *ty = Swig_symbol_template_deftype(rty, 0); String *tyq = Swig_symbol_type_qualify(ty, 0); hashtype = SwigType_remove_global_scope_prefix(tyq); @@ -733,6 +764,7 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type SwigType *oldctype = ctype; ctype = SwigType_typedef_resolve(ctype_unstripped); Delete(oldctype); + Delete(ctype_unstripped); ctype_unstripped = Copy(ctype); } } @@ -1876,6 +1908,21 @@ static List *split_embedded_typemap(String *s) { return args; } +/* ----------------------------------------------------------------------------- + * Swig_typemap_replace_embedded_typemap() + * + * For special variable macro $typemap(...) expansion outside of typemaps. + * Only limited usage works as most typemap special variables ($1, $input etc) + * are not expanded correctly outside of typemaps. + * ----------------------------------------------------------------------------- */ + +void Swig_typemap_replace_embedded_typemap(String *s, Node *file_line_node) { + Setfile(s, Getfile(file_line_node)); + Setline(s, Getline(file_line_node)); + Replaceall(s, "$typemap", "$TYPEMAP"); + replace_embedded_typemap(s, 0, 0, file_line_node); +} + /* ----------------------------------------------------------------------------- * replace_embedded_typemap() * diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index b2832b6a9..69fb6662b 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -43,12 +43,12 @@ * All type constructors are denoted by a trailing '.': * * 'p.' = Pointer (*) - * 'r.' = Reference (&) - * 'z.' = Rvalue reference (&&) + * 'r.' = Reference or ref-qualifier (&) + * 'z.' = Rvalue reference or ref-qualifier (&&) * 'a(n).' = Array of size n [n] * 'f(..,..).' = Function with arguments (args) - * 'q(str).' = Qualifier (such as const or volatile) (const, volatile) - * 'm(qual).' = Pointer to member (qual::*) + * 'q(str).' = Qualifier, such as const or volatile (cv-qualifier) + * 'm(cls).' = Pointer to member (cls::*) * * The complete type representation for varargs is: * 'v(...)' @@ -183,9 +183,10 @@ SwigType *SwigType_del_element(SwigType *t) { * SwigType_pop() * * Pop one type element off the type. - * Example: t in: q(const).p.Integer - * t out: p.Integer - * result: q(const). + * For example: + * t in: q(const).p.Integer + * t out: p.Integer + * result: q(const). * ----------------------------------------------------------------------------- */ SwigType *SwigType_pop(SwigType *t) { @@ -771,7 +772,6 @@ SwigType *SwigType_array_type(const SwigType *ty) { * Functions * * SwigType_add_function() - * SwigType_del_function() * SwigType_isfunction() * SwigType_pop_function() * @@ -795,14 +795,36 @@ SwigType *SwigType_add_function(SwigType *t, ParmList *parms) { return t; } +/* ----------------------------------------------------------------------------- + * SwigType_pop_function() + * + * Pop and return the function from the input type leaving the function's return + * type, if any. + * For example: + * t in: q(const).f().p. + * t out: p. + * result: q(const).f(). + * ----------------------------------------------------------------------------- */ + SwigType *SwigType_pop_function(SwigType *t) { SwigType *f = 0; SwigType *g = 0; char *c = Char(t); - if (strncmp(c, "q(", 2) == 0) { + if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) { + /* Remove ref-qualifier */ f = SwigType_pop(t); c = Char(t); } + if (strncmp(c, "q(", 2) == 0) { + /* Remove cv-qualifier */ + String *qual = SwigType_pop(t); + if (f) { + SwigType_push(qual, f); + Delete(f); + } + f = qual; + c = Char(t); + } if (strncmp(c, "f(", 2)) { printf("Fatal error. SwigType_pop_function applied to non-function.\n"); abort(); @@ -814,14 +836,54 @@ SwigType *SwigType_pop_function(SwigType *t) { return g; } +/* ----------------------------------------------------------------------------- + * SwigType_pop_function_qualifiers() + * + * Pop and return the function qualifiers from the input type leaving the rest of + * function declaration. Returns NULL if no qualifiers. + * For example: + * t in: r.q(const).f().p. + * t out: f().p. + * result: r.q(const) + * ----------------------------------------------------------------------------- */ + +SwigType *SwigType_pop_function_qualifiers(SwigType *t) { + SwigType *qualifiers = 0; + char *c = Char(t); + if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) { + /* Remove ref-qualifier */ + String *qual = SwigType_pop(t); + qualifiers = qual; + c = Char(t); + } + if (strncmp(c, "q(", 2) == 0) { + /* Remove cv-qualifier */ + String *qual = SwigType_pop(t); + if (qualifiers) { + SwigType_push(qual, qualifiers); + Delete(qualifiers); + } + qualifiers = qual; + } + assert(Strncmp(t, "f(", 2) == 0); + + return qualifiers; +} + int SwigType_isfunction(const SwigType *t) { char *c; if (!t) { return 0; } c = Char(t); + if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) { + /* Might be a function with a ref-qualifier, skip over */ + c += 2; + if (!*c) + return 0; + } if (strncmp(c, "q(", 2) == 0) { - /* Might be a 'const' function. Try to skip over the 'const' */ + /* Might be a function with a cv-qualifier, skip over */ c = strchr(c, '.'); if (c) c++; diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index e11fc781a..7564db1a6 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -42,10 +42,15 @@ * "name" - Scope name * "qname" - Fully qualified typename * "typetab" - Type table containing typenames and typedef information + * For a given key in the typetab table, the value is a fully + * qualified name if not pointing to itself. * "symtab" - Hash table of symbols defined in a scope * "inherit" - List of inherited scopes * "parent" - Parent scope * + * The contents of these tables can be viewed for debugging using the -debug-typedef + * option which calls SwigType_print_scope(). + * * Typedef information is stored in the "typetab" hash table. For example, * if you have these declarations: * @@ -53,8 +58,7 @@ * typedef A B; * typedef B *C; * - * typetab is built as follows: - * + * typetab in scope '' contains: * "A" : "int" * "B" : "A" * "C" : "p.B" @@ -67,31 +71,76 @@ * ---> a(40).p.p.A (B --> A) * ---> a(40).p.p.int (A --> int) * + * + * Using declarations are stored in the "typetab" hash table. For example, + * + * namespace NN { + * struct SS {}; + * } + * namespace N { + * struct S {}; + * using NN::SS; + * } + * using N::S; + * + * typetab in scope '' contains: + * "S" : "N::S" + * + * and typetab in scope 'N' contains: + * "SS" : "NN::SS" + * "S" : "S" + * + * * For inheritance, SWIG tries to resolve types back to the base class. For instance, if * you have this: * - * class Foo { - * public: - * typedef int Integer; - * }; + * class Foo { + * public: + * typedef int Integer; + * }; + * struct Bar : public Foo { + * void blah(Integer x); + * }; * - * class Bar : public Foo { - * void blah(Integer x); - * }; + * In this case typetab in scope '' contains: + * "Foo" : "Foo" + * "Bar" : "Bar" + * and scope 'Foo' contains: + * "Integer" : "int" + * and scope 'Bar' inherits from 'Foo' but is empty (observe that blah is not a scope or typedef) * * The argument type of Bar::blah will be set to Foo::Integer. * + * + * The scope-inheritance mechanism is used to manage C++ using directives. + * + * namespace XX { + * class CC {}; + * } + * namespace X { + * class C {}; + * using namespace XX; + * } + * using namespace X; + * + * typetab in scope '' inherits from 'X' + * typetab in scope 'X' inherits from 'XX' and contains: + * "C" : "C" + * typetab in scope 'XX' contains: + * "CC" : "CC" + * + * * The scope-inheritance mechanism is used to manage C++ namespace aliases. * For example, if you have this: * - * namespace Foo { - * typedef int Integer; - * } + * namespace Foo { + * typedef int Integer; + * } * - * namespace F = Foo; + * namespace F = Foo; * - * In this case, "F::" is defined as a scope that "inherits" from Foo. Internally, - * "F::" will merely be an empty scope that refers to Foo. SWIG will never + * In this case, F is defined as a scope that "inherits" from Foo. Internally, + * F will merely be an empty scope that points to Foo. SWIG will never * place new type information into a namespace alias---attempts to do so * will generate a warning message (in the parser) and will place information into * Foo instead. @@ -166,6 +215,7 @@ void SwigType_typesystem_init() { * ----------------------------------------------------------------------------- */ int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) { + /* Printf(stdout, "typedef %s %s\n", type, name); */ if (Getattr(current_typetab, name)) return -1; /* Already defined */ if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */ @@ -248,10 +298,26 @@ void SwigType_new_scope(const_String_or_char_ptr name) { ttab = NewHash(); Setattr(s, "typetab", ttab); - /* Build fully qualified name and */ + /* Build fully qualified name */ qname = SwigType_scope_name(s); +#if 1 + { + /* TODO: only do with templates? What happens with non-templates with code below? */ + String *stripped_qname; + stripped_qname = SwigType_remove_global_scope_prefix(qname); + /* Use fully qualified name for hash key without unary scope prefix, qname may contain unary scope */ + Setattr(scopes, stripped_qname, s); + Setattr(s, "qname", qname); + /* + Printf(stdout, "SwigType_new_scope stripped %s %s\n", qname, stripped_qname); + */ + Delete(stripped_qname); + } +#else + Printf(stdout, "SwigType_new_scope %s\n", qname); Setattr(scopes, qname, s); Setattr(s, "qname", qname); +#endif Delete(qname); current_scope = s; @@ -418,12 +484,14 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) { Typetab *s_orig = s; String *nnameprefix = 0; static int check_parent = 1; + int is_template = 0; if (Getmark(s)) return 0; Setmark(s, 1); - if (SwigType_istemplate(nameprefix)) { + is_template = SwigType_istemplate(nameprefix); + if (is_template) { nnameprefix = SwigType_typedef_resolve_all(nameprefix); nameprefix = nnameprefix; } @@ -437,10 +505,12 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) { } else { full = NewString(nameprefix); } - if (Getattr(scopes, full)) { - s = Getattr(scopes, full); - } else { - s = 0; + s = Getattr(scopes, full); + if (!s && is_template) { + /* try look up scope with all the unary scope operators within the template parameter list removed */ + SwigType *full_stripped = SwigType_remove_global_scope_prefix(full); + s = Getattr(scopes, full_stripped); + Delete(full_stripped); } Delete(full); if (s) { @@ -500,7 +570,7 @@ static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) { List *inherit; Typetab *parent; - /* if (!s) return 0; *//* now is checked bellow */ + /* if (!s) return 0; *//* now is checked below */ /* Printf(stdout,"Typetab %s : %s\n", Getattr(s,"name"), base); */ if (!Getmark(s)) { @@ -541,8 +611,11 @@ static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) { /* ----------------------------------------------------------------------------- * template_parameters_resolve() * - * For use with templates only. The template parameters are resolved. If none - * of the parameters can be resolved, zero is returned. + * For use with templates only. Attempts to resolve one template parameter. + * + * If one of the template parameters can be resolved, the type is returned with + * just the one parameter resolved and the remaining parameters left as is. + * If none of the template parameters can be resolved, zero is returned. * ----------------------------------------------------------------------------- */ static String *template_parameters_resolve(const String *base) { @@ -574,14 +647,15 @@ static String *template_parameters_resolve(const String *base) { if ((i + 1) < sz) Append(type, ","); } - Append(type, ")>"); - Append(type, suffix); - Delete(suffix); - Delete(tparms); - if (!rep) { + if (rep) { + Append(type, ")>"); + Append(type, suffix); + } else { Delete(type); type = 0; } + Delete(suffix); + Delete(tparms); return type; } @@ -592,6 +666,17 @@ static SwigType *typedef_resolve(Typetab *s, String *base) { /* ----------------------------------------------------------------------------- * SwigType_typedef_resolve() + * + * Given a type declaration, this function looks to reduce/resolve the type via a + * typedef (including via C++ using declarations). + * + * If it is able to find a typedef, the resolved type is returned. If no typedef + * is found NULL is returned. The type name is resolved in the current scope. + * The type returned is not always fully qualified for the global scope, it is + * valid for use in the current scope. If the current scope is global scope, a + * fully qualified type should be returned. + * + * Some additional notes are in Doc/Manual/Extending.html. * ----------------------------------------------------------------------------- */ /* #define SWIG_DEBUG */ @@ -718,6 +803,25 @@ SwigType *SwigType_typedef_resolve(const SwigType *t) { } } + if (!type && SwigType_istemplate(base)) { + String *tprefix = SwigType_templateprefix(base); + String *rtprefix = SwigType_typedef_resolve(tprefix); + /* We're looking for a using declaration on the template prefix to resolve the template prefix + * in another scope. Using declaration do not have template parameters. */ + if (rtprefix && !SwigType_istemplate(rtprefix)) { + String *tsuffix = SwigType_templatesuffix(base); + String *targs = SwigType_templateargs(base); + type = NewString(rtprefix); + newtype = 1; + Append(type, targs); + Append(type, tsuffix); + Delete(targs); + Delete(tsuffix); + Delete(rtprefix); + } + Delete(tprefix); + } + if (type && (Equal(base, type))) { if (newtype) Delete(type); @@ -735,10 +839,8 @@ SwigType *SwigType_typedef_resolve(const SwigType *t) { newtype = 1; type = template_parameters_resolve(base); } - if (namebase) - Delete(namebase); - if (nameprefix) - Delete(nameprefix); + Delete(namebase); + Delete(nameprefix); } else { if (SwigType_isfunction(base)) { List *parms; @@ -911,6 +1013,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) { return Copy(r); } +#ifdef SWIG_DEBUG + Printf(stdout, "SwigType_typedef_resolve_all start ... %s\n", t); +#endif /* Recursively resolve the typedef */ r = NewString(t); while ((n = SwigType_typedef_resolve(r))) { @@ -931,6 +1036,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) { Delete(key); Delete(rr); } +#ifdef SWIG_DEBUG + Printf(stdout, "SwigType_typedef_resolve_all end === %s => %s\n", t, r); +#endif return r; } @@ -938,8 +1046,17 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) { /* ----------------------------------------------------------------------------- * SwigType_typedef_qualified() * - * Given a type declaration, this function tries to fully qualify it according to - * typedef scope rules. + * Given a type declaration, this function tries to fully qualify it so that the + * resulting type can be used in the global scope. The type name is resolved in + * the current scope. + * + * It provides a fully qualified name, not necessarily a fully expanded name. + * When a using declaration or using directive is found the type may not be fully + * expanded, but it will be resolved and fully qualified for use in the global scope. + * + * This function is for looking up scopes to qualify a type. It does not resolve + * C typedefs, it just qualifies them. See SwigType_typedef_resolve for resolving. + * * If the unary scope operator (::) is used as a prefix to the type to denote global * scope, it is left in place. * ----------------------------------------------------------------------------- */ @@ -1000,20 +1117,14 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) { out of the current scope */ Typetab *cs = current_scope; - while (cs) { - String *qs = SwigType_scope_name(cs); - if (Len(qs)) { - Append(qs, "::"); - } - Append(qs, e); - if (Getattr(scopes, qs)) { + if (cs) { + Typetab *found_scope = SwigType_find_scope(cs, e); + if (found_scope) { + String *qs = SwigType_scope_name(found_scope); Clear(e); Append(e, qs); Delete(qs); - break; } - Delete(qs); - cs = Getattr(cs, "parent"); } } } @@ -1029,10 +1140,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) { Parm *p; List *parms; ty = Swig_symbol_template_deftype(e, current_symtab); - /* - String *dt = Swig_symbol_template_deftype(e, current_symtab); - ty = Swig_symbol_type_qualify(dt, 0); - */ e = ty; parms = SwigType_parmlist(e); tprefix = SwigType_templateprefix(e); @@ -1099,9 +1206,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) { Delete(tprefix); Delete(qprefix); Delete(parms); - /* - Delete(dt); - */ } Append(result, e); Delete(ty); @@ -1181,7 +1285,7 @@ int SwigType_typedef_using(const_String_or_char_ptr name) { String *defined_name = 0; - /* Printf(stdout,"using %s\n", name); */ + /* Printf(stdout, "using %s\n", name); */ if (!Swig_scopename_check(name)) return -1; /* Not properly qualified */ @@ -1436,7 +1540,7 @@ SwigType *SwigType_alttype(const SwigType *t, int local_tmap) { } } else { if (SwigType_issimple(td) && SwigType_istemplate(td)) { - use_wrapper = !n || !GetFlag(n, "feature:novaluewrapper"); + use_wrapper = 1; } } } diff --git a/TODO b/TODO index 01d9a8d78..38ab4605d 100644 --- a/TODO +++ b/TODO @@ -275,74 +275,6 @@ Mzscheme ** Add shadow class support for the Swindle system. -Pike ----- - -* Decide how to handle global variables (probably using something - like the Python module's cvar). Affects Examples/pike/simple. - -* Decide how to handle static class member functions and member - variables. - -* Should investigate the possibility of generating .cmod files - in addition to straight C/C++ code for extensions. - -Common Lisp ------------ - -* Random thoughts by mkoeppe on supporting Common Lisp implementations: - - There are many different Foreign Function Interfaces (FFI) for - the various CL implementations. Probably SWIG should interface - to UFFI, a least-common-denominator FFI that supports many - implementations. - - Via the s-expression SWIG module we can export SWIG's parse - tree and import it into CL. It remains to check if all - relevant information is dumped (for instance, the type - information). Experimental code is available to generate - low-level UFFI declarations from this parse tree. - - However, for wrapping C++, we also need to create C wrappers - because most FFIs cannot directly import C++. A CL SWIG module - could be exporting both these wrappers and UFFI declarations. - I have experimental code (not checked in yet) that does this. - - This is fine for generating low-level wrappers. But how do we - support user typemaps (like converting lists and vectors to C - arrays on input)? We have to generate Lisp code that does the - conversion and then calls the low-level wrapper. If we - generate Lisp code, it should be beautiful and readable. - Therefore, we need at least a Lisp pretty printer. A Lisp - pretty printer works best when the Lisp program is represented - not as text but as Lisp data. Moreover, typemap writers will - feel very much constrained by SWIG's capabilities for - generating wrapper code, when compared to writing Lisp macros. - Thus we would need half a re-implementation of Lisp in SWIG to - make users happy. - - The solution could be the following: - -** Build a SWIG library (again) and load it into a Common Lisp - implementation. - - The FFI declarations could be written manually, or this could - be bootstrapped via the s-expression module or the primitive - UFFI wrappers. This should be easy because SWIG's API is quite - simple. - - The embedded SWIG would be driven by a CL program. High-level - typemaps would be written as Lisp programs that generate Lisp - code. - -ALLEGROCL ------ -These first three will remove most of the warnings from most of the -remaining checkpartial tests that are failing. -**** Throws typemap support -**** const typemaps -**** long long typemaps - Ocaml ----- ** I've been working with my camlp4 module and type information diff --git a/Tools/config/ax_boost_base.m4 b/Tools/config/ax_boost_base.m4 index f3279f2b7..f5a935cd6 100644 --- a/Tools/config/ax_boost_base.m4 +++ b/Tools/config/ax_boost_base.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_base.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_base.html # =========================================================================== # # SYNOPSIS @@ -33,7 +33,15 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 26 +#serial 45 + +# example boost program (need to pass version) +m4_define([_AX_BOOST_BASE_PROGRAM], + [AC_LANG_PROGRAM([[ +#include +]],[[ +(void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < ($1))])); +]])]) AC_DEFUN([AX_BOOST_BASE], [ @@ -44,104 +52,121 @@ AC_ARG_WITH([boost], or disable it (ARG=no) @<:@ARG=yes@:>@ ])], [ - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ac_boost_path="" - else - want_boost="yes" - ac_boost_path="$withval" - fi + AS_CASE([$withval], + [no],[want_boost="no";_AX_BOOST_BASE_boost_path=""], + [yes],[want_boost="yes";_AX_BOOST_BASE_boost_path=""], + [want_boost="yes";_AX_BOOST_BASE_boost_path="$withval"]) ], [want_boost="yes"]) AC_ARG_WITH([boost-libdir], - AS_HELP_STRING([--with-boost-libdir=LIB_DIR], - [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]), - [ - if test -d "$withval" - then - ac_boost_lib_path="$withval" - else - AC_MSG_ERROR(--with-boost-libdir expected directory name) - fi - ], - [ac_boost_lib_path=""] -) + [AS_HELP_STRING([--with-boost-libdir=LIB_DIR], + [Force given directory for boost libraries. + Note that this will override library path detection, + so use this parameter only if default library detection fails + and you know exactly where your boost libraries are located.])], + [ + AS_IF([test -d "$withval"], + [_AX_BOOST_BASE_boost_lib_path="$withval"], + [AC_MSG_ERROR([--with-boost-libdir expected directory name])]) + ], + [_AX_BOOST_BASE_boost_lib_path=""]) -if test "x$want_boost" = "xyes"; then - boost_lib_version_req=ifelse([$1], ,1.20.0,$1) - boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'` - boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'` - boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'` - boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` - if test "x$boost_lib_version_req_sub_minor" = "x" ; then - boost_lib_version_req_sub_minor="0" - fi - WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` - AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req) +BOOST_LDFLAGS="" +BOOST_CPPFLAGS="" +AS_IF([test "x$want_boost" = "xyes"], + [_AX_BOOST_BASE_RUNDETECT([$1],[$2],[$3])]) +AC_SUBST(BOOST_CPPFLAGS) +AC_SUBST(BOOST_LDFLAGS) +]) + + +# convert a version string in $2 to numeric and affect to polymorphic var $1 +AC_DEFUN([_AX_BOOST_BASE_TONUMERICVERSION],[ + AS_IF([test "x$2" = "x"],[_AX_BOOST_BASE_TONUMERICVERSION_req="1.20.0"],[_AX_BOOST_BASE_TONUMERICVERSION_req="$2"]) + _AX_BOOST_BASE_TONUMERICVERSION_req_shorten=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\.[[0-9]]*\)'` + _AX_BOOST_BASE_TONUMERICVERSION_req_major=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\)'` + AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_major" = "x"], + [AC_MSG_ERROR([You should at least specify libboost major version])]) + _AX_BOOST_BASE_TONUMERICVERSION_req_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.\([[0-9]]*\)'` + AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_minor" = "x"], + [_AX_BOOST_BASE_TONUMERICVERSION_req_minor="0"]) + _AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` + AS_IF([test "X$_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor" = "X"], + [_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor="0"]) + _AX_BOOST_BASE_TONUMERICVERSION_RET=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req_major \* 100000 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_minor \* 100 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor` + AS_VAR_SET($1,$_AX_BOOST_BASE_TONUMERICVERSION_RET) +]) + +dnl Run the detection of boost should be run only if $want_boost +AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[ + _AX_BOOST_BASE_TONUMERICVERSION(WANT_BOOST_VERSION,[$1]) succeeded=no + + AC_REQUIRE([AC_CANONICAL_HOST]) dnl On 64-bit systems check for system libraries in both lib64 and lib. dnl The former is specified by FHS, but e.g. Debian does not adhere to dnl this (as it rises problems for generic multi-arch support). dnl The last entry in the list is chosen by default when no libraries dnl are found, e.g. when only header-only libraries are installed! - libsubdirs="lib" - ax_arch=`uname -m` - case $ax_arch in - x86_64) - libsubdirs="lib64 libx32 lib lib64" - ;; - ppc64|s390x|sparc64|aarch64|ppc64le) - libsubdirs="lib64 lib lib64 ppc64le" - ;; - esac + AS_CASE([${host_cpu}], + [x86_64],[libsubdirs="lib64 libx32 lib lib64"], + [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64],[libsubdirs="lib64 lib lib64"], + [libsubdirs="lib"] + ) dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give dnl them priority over the other paths since, if libs are found there, they dnl are almost assuredly the ones desired. - AC_REQUIRE([AC_CANONICAL_HOST]) - libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs" - - case ${host_cpu} in - i?86) - libsubdirs="lib/i386-${host_os} $libsubdirs" - ;; - esac + AS_CASE([${host_cpu}], + [i?86],[multiarch_libsubdir="lib/i386-${host_os}"], + [multiarch_libsubdir="lib/${host_cpu}-${host_os}"] + ) dnl first we check the system location for boost libraries dnl this location ist chosen if boost libraries are installed with the --layout=system option dnl or if you install boost with RPM - if test "$ac_boost_path" != ""; then - BOOST_CPPFLAGS="-I$ac_boost_path/include" - for ac_boost_path_tmp in $libsubdirs; do - if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then - BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp" - break - fi - done - elif test "$cross_compiling" != yes; then - for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then - for libsubdir in $libsubdirs ; do - if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi + AS_IF([test "x$_AX_BOOST_BASE_boost_path" != "x"],[ + AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) includes in "$_AX_BOOST_BASE_boost_path/include"]) + AS_IF([test -d "$_AX_BOOST_BASE_boost_path/include" && test -r "$_AX_BOOST_BASE_boost_path/include"],[ + AC_MSG_RESULT([yes]) + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include" + for _AX_BOOST_BASE_boost_path_tmp in $multiarch_libsubdir $libsubdirs; do + AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) lib path in "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"]) + AS_IF([test -d "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" && test -r "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" ],[ + AC_MSG_RESULT([yes]) + BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"; + break; + ], + [AC_MSG_RESULT([no])]) + done],[ + AC_MSG_RESULT([no])]) + ],[ + if test X"$cross_compiling" = Xyes; then + search_libsubdirs=$multiarch_libsubdir + else + search_libsubdirs="$multiarch_libsubdir $libsubdirs" + fi + for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do + if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then + for libsubdir in $search_libsubdirs ; do + if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done - BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir" - BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" + BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path_tmp/$libsubdir" + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path_tmp/include" break; fi done - fi + ]) dnl overwrite ld flags if we have required special directory with dnl --with-boost-libdir parameter - if test "$ac_boost_lib_path" != ""; then - BOOST_LDFLAGS="-L$ac_boost_lib_path" - fi + AS_IF([test "x$_AX_BOOST_BASE_boost_lib_path" != "x"], + [BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_lib_path"]) + AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION)]) CPPFLAGS_SAVED="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" export CPPFLAGS @@ -152,60 +177,61 @@ if test "x$want_boost" = "xyes"; then AC_REQUIRE([AC_PROG_CXX]) AC_LANG_PUSH(C++) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - @%:@include - ]], [[ - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - ]])],[ + AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[ AC_MSG_RESULT(yes) succeeded=yes found_system=yes - ],[ - ]) + ],[]) AC_LANG_POP([C++]) dnl if we found no boost with system layout we search for boost libraries dnl built and installed without the --layout=system option or for a staged(not installed) version - if test "x$succeeded" != "xyes"; then + if test "x$succeeded" != "xyes" ; then CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" BOOST_CPPFLAGS= - BOOST_LDFLAGS= + if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then + BOOST_LDFLAGS= + fi _version=0 - if test "$ac_boost_path" != ""; then - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` + if test -n "$_AX_BOOST_BASE_boost_path" ; then + if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path"; then + for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do + _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then + if test "x$V_CHECK" = "x1" ; then _version=$_version_tmp fi VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` - BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include/boost-$VERSION_UNDERSCORE" done dnl if nothing found search for layout used in Windows distributions if test -z "$BOOST_CPPFLAGS"; then - if test -d "$ac_boost_path/boost" && test -r "$ac_boost_path/boost"; then - BOOST_CPPFLAGS="-I$ac_boost_path" + if test -d "$_AX_BOOST_BASE_boost_path/boost" && test -r "$_AX_BOOST_BASE_boost_path/boost"; then + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path" fi fi + dnl if we found something and BOOST_LDFLAGS was unset before + dnl (because "$_AX_BOOST_BASE_boost_lib_path" = ""), set it here. + if test -n "$BOOST_CPPFLAGS" && test -z "$BOOST_LDFLAGS"; then + for libsubdir in $libsubdirs ; do + if ls "$_AX_BOOST_BASE_boost_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi + done + BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$libsubdir" + fi fi else - if test "$cross_compiling" != yes; then - for ac_boost_path in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` + if test "x$cross_compiling" != "xyes" ; then + for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do + if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path" ; then + for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do + _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then + if test "x$V_CHECK" = "x1" ; then _version=$_version_tmp - best_path=$ac_boost_path + best_path=$_AX_BOOST_BASE_boost_path fi done fi @@ -213,7 +239,7 @@ if test "x$want_boost" = "xyes"; then VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" - if test "$ac_boost_lib_path" = ""; then + if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then for libsubdir in $libsubdirs ; do if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done @@ -221,7 +247,7 @@ if test "x$want_boost" = "xyes"; then fi fi - if test "x$BOOST_ROOT" != "x"; then + if test -n "$BOOST_ROOT" ; then for libsubdir in $libsubdirs ; do if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done @@ -230,7 +256,7 @@ if test "x$want_boost" = "xyes"; then stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'` V_CHECK=`expr $stage_version_shorten \>\= $_version` - if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then + if test "x$V_CHECK" = "x1" && test -z "$_AX_BOOST_BASE_boost_lib_path" ; then AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT) BOOST_CPPFLAGS="-I$BOOST_ROOT" BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" @@ -245,34 +271,23 @@ if test "x$want_boost" = "xyes"; then export LDFLAGS AC_LANG_PUSH(C++) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - @%:@include - ]], [[ - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - ]])],[ + AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[ AC_MSG_RESULT(yes) succeeded=yes found_system=yes - ],[ - ]) + ],[]) AC_LANG_POP([C++]) fi - if test "$succeeded" != "yes" ; then - if test "$_version" = "0" ; then - AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation.]]) + if test "x$succeeded" != "xyes" ; then + if test "x$_version" = "x0" ; then + AC_MSG_NOTICE([[We could not detect the boost libraries (version $1 or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation.]]) else AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).]) fi # execute ACTION-IF-NOT-FOUND (if present): ifelse([$3], , :, [$3]) else - AC_SUBST(BOOST_CPPFLAGS) - AC_SUBST(BOOST_LDFLAGS) AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available]) # execute ACTION-IF-FOUND (if present): ifelse([$2], , :, [$2]) @@ -280,6 +295,5 @@ if test "x$want_boost" = "xyes"; then CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" -fi ]) diff --git a/Tools/config/ax_compare_version.m4 b/Tools/config/ax_compare_version.m4 index 74dc0fdd9..ffb4997e8 100644 --- a/Tools/config/ax_compare_version.m4 +++ b/Tools/config/ax_compare_version.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_compare_version.html +# https://www.gnu.org/software/autoconf-archive/ax_compare_version.html # =========================================================================== # # SYNOPSIS @@ -79,7 +79,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 11 +#serial 13 dnl ######################################################################### AC_DEFUN([AX_COMPARE_VERSION], [ @@ -146,7 +146,7 @@ x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"` ], [.+],[ AC_WARNING( - [illegal OP numeric parameter: $2]) + [invalid OP numeric parameter: $2]) ],[]) # Pad zeros at end of numbers to make same length. @@ -162,7 +162,7 @@ x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"` [ne],[ test "x$A" != "x$B" && ax_compare_version=true ],[ - AC_WARNING([illegal OP parameter: $2]) + AC_WARNING([invalid OP parameter: $2]) ]) ]) diff --git a/Tools/config/ax_path_generic.m4 b/Tools/config/ax_path_generic.m4 index f77fc78d6..87966890b 100644 --- a/Tools/config/ax_path_generic.m4 +++ b/Tools/config/ax_path_generic.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_path_generic.html +# https://www.gnu.org/software/autoconf-archive/ax_path_generic.html # =========================================================================== # # SYNOPSIS @@ -14,11 +14,11 @@ # The script must support `--cflags' and `--libs' args. If MINIMUM-VERSION # is specified, the script must also support the `--version' arg. If the # `--with-library-[exec-]prefix' arguments to ./configure are given, it -# must also support `--prefix' and `--exec-prefix'. Prefereable use +# must also support `--prefix' and `--exec-prefix'. Preferably use # CONFIG-SCRIPTS as config script, CFLAGS-ARG instead of `--cflags` and # LIBS-ARG instead of `--libs`, if given. # -# The SED-EXPR-EXTRACTOR parameter representes the expression used in sed +# The SED-EXPR-EXTRACTOR parameter represents the expression used in sed # to extract the version number. Use it if your 'foo-config --version' # dumps something like 'Foo library v1.0.0 (alfa)' instead of '1.0.0'. # @@ -69,7 +69,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 13 +#serial 17 AU_ALIAS([AC_PATH_GENERIC], [AX_PATH_GENERIC]) AC_DEFUN([AX_PATH_GENERIC],[ diff --git a/Tools/mkdist.py b/Tools/mkdist.py index 11a0dd6cd..47cf8e765 100755 --- a/Tools/mkdist.py +++ b/Tools/mkdist.py @@ -1,100 +1,103 @@ #!/usr/bin/env python -# This script builds a swig-x.y.z distribution. -# Usage: mkdist.py version branch, where version should be x.y.z and branch is normally 'master' - import sys -import string import os import subprocess def failed(): - print "mkdist.py failed to complete" - sys.exit(2) + print("mkdist.py failed to complete") + sys.exit(2) +import argparse +parser = argparse.ArgumentParser(description="Build a SWIG distribution tarball swig-x.y.z.tar.gz") +parser.add_argument("version", help="version string in format x.y.z") +parser.add_argument("-b", "--branch", required=False, default="master", help="git branch name to create tarball from [master]") +parser.add_argument("-f", "--force-tag", required=False, action="store_true", help="force tag (replace git tag if it already exists)") +parser.add_argument("-s", "--skip-checks", required=False, action="store_true", help="skip checks (that local and remote repos are in sync)") +args = parser.parse_args() -try: - version = sys.argv[1] - dirname = "swig-" + version - branch = sys.argv[2] -except: - print "Usage: mkdist.py version branch, where version should be x.y.z and branch is normally 'master'" - sys.exit(1) +version = args.version +branch = args.branch +dirname = "swig-" + version +force_tag = args.force_tag +skip_checks = args.skip_checks if sys.version_info[0:2] < (2, 7): - print "Error: Python 2.7 is required" - sys.exit(3) - + print("Error: Python 2.7 or higher is required") + sys.exit(3) # Check name matches normal unix conventions -if string.lower(dirname) != dirname: - print "directory name ("+dirname+") should be in lowercase" - sys.exit(3) +if dirname.lower() != dirname: + print("directory name (" + dirname + ") should be in lowercase") + sys.exit(3) # If directory and tarball exist, remove it -print "Removing ", dirname -os.system("rm -rf "+dirname) +print("Removing " + dirname) +os.system("rm -rf " + dirname) -print "Removing "+dirname+".tar if exists" -os.system("rm -f "+dirname+".tar.gz") +print("Removing " + dirname + ".tar if exists") +os.system("rm -f " + dirname + ".tar.gz") -print "Removing "+dirname+".tar.gz if exists" -os.system("rm -f "+dirname+".tar") +print("Removing " + dirname + ".tar.gz if exists") +os.system("rm -f " + dirname + ".tar") # Grab the code from git -print "Checking git repository is in sync with remote repository" +print("Checking there are no local changes in git repo") os.system("git remote update origin") == 0 or failed() command = ["git", "status", "--porcelain", "-uno"] out = subprocess.check_output(command) if out.strip() != "": - print "Local git repository has modifications" - print " ".join(command) - print out - sys.exit(3) + print("Local git repository has modifications") + print(" ".join(command)) + print(out) + sys.exit(3) -command = ["git", "log", "--oneline", branch + "..origin/" + branch] -out = subprocess.check_output(command) -if out.strip() != "": - print "Remote repository has additional modifications to local repository" - print " ".join(command) - print out - sys.exit(3) +if not skip_checks: + print("Checking git repository is in sync with remote repository") + command = ["git", "log", "--oneline", branch + "..origin/" + branch] + out = subprocess.check_output(command) + if out.strip() != "": + print("Remote repository has additional modifications to local repository") + print(" ".join(command)) + print(out) + sys.exit(3) -command = ["git", "log", "--oneline", "origin/" + branch + ".." + branch] -out = subprocess.check_output(command) -if out.strip() != "": - print "Local repository has modifications not pushed to the remote repository" - print "These should be pushed and checked that they pass Continuous Integration testing before continuing" - print " ".join(command) - print out - sys.exit(3) + command = ["git", "log", "--oneline", "origin/" + branch + ".." + branch] + out = subprocess.check_output(command) + if out.strip() != "": + print("Local repository has modifications not pushed to the remote repository") + print("These should be pushed and checked that they pass Continuous Integration testing before continuing") + print(" ".join(command)) + print(out) + sys.exit(3) -print "Tagging release" +print("Tagging release") tag = "'rel-" + version + "'" -os.system("git tag -a -m " + tag + " " + tag) == 0 or failed() +force = "-f " if force_tag else "" +os.system("git tag -a -m " + tag + " " + force + tag) == 0 or failed() outdir = os.path.basename(os.getcwd()) + "/" + dirname + "/" -print "Grabbing tagged release git repository using 'git archive' into " + outdir +print("Grabbing tagged release git repository using 'git archive' into " + outdir) os.system("(cd .. && git archive --prefix=" + outdir + " " + tag + " . | tar -xf -)") == 0 or failed() # Go build the system -print "Building system" -os.system("cd "+dirname+" && ./autogen.sh") == 0 or failed() -os.system("cd "+dirname+"/Source/CParse && bison -y -d parser.y && mv y.tab.c parser.c && mv y.tab.h parser.h") == 0 or failed() -os.system("cd "+dirname+" && make -f Makefile.in libfiles srcdir=./") == 0 or failed() +print("Building system") +os.system("cd " + dirname + " && ./autogen.sh") == 0 or failed() +os.system("cd " + dirname + "/Source/CParse && bison -y -d parser.y && mv y.tab.c parser.c && mv y.tab.h parser.h") == 0 or failed() +os.system("cd " + dirname + " && make -f Makefile.in libfiles srcdir=./") == 0 or failed() # Remove autoconf files -os.system("find "+dirname+" -name autom4te.cache -exec rm -rf {} \\;") +os.system("find " + dirname + " -name autom4te.cache -exec rm -rf {} \\;") # Build documentation -print "Building html documentation" -os.system("cd "+dirname+"/Doc/Manual && make all clean-baks") == 0 or failed() +print("Building html documentation") +os.system("cd " + dirname + "/Doc/Manual && make all clean-baks") == 0 or failed() # Build the tar-ball -os.system("tar -cf "+dirname+".tar "+dirname) == 0 or failed() -os.system("gzip "+dirname+".tar") == 0 or failed() +os.system("tar -cf " + dirname + ".tar " + dirname) == 0 or failed() +os.system("gzip " + dirname + ".tar") == 0 or failed() -print "Finished building "+dirname+".tar.gz" +print("Finished building " + dirname + ".tar.gz") diff --git a/Tools/mkrelease.py b/Tools/mkrelease.py index ec9a2b76a..014cef227 100755 --- a/Tools/mkrelease.py +++ b/Tools/mkrelease.py @@ -1,49 +1,56 @@ #!/usr/bin/env python -# This script builds the SWIG source tarball, creates the Windows executable and the Windows zip package -# and uploads them both to SF ready for release. Also uploaded are the release notes. import sys -import string import os def failed(message): if message == "": - print "mkrelease.py failed to complete" + print("mkrelease.py failed to complete") else: - print message + print(message) sys.exit(2) -try: - version = sys.argv[1] - branch = sys.argv[2] - username = sys.argv[3] -except: - print "Usage: python mkrelease.py version branch username" - print "where version should be x.y.z and username is your SF username" - sys.exit(1) +import argparse +parser = argparse.ArgumentParser(description="Build a SWIG distribution source tarball swig-x.y.z.tar.gz and the Windows zip package swigwin-x.y.z.zip.\nUpload them both to SourceForge ready for release.\nThe release notes are also uploaded.") +parser.add_argument("version", help="version string in format x.y.z") +parser.add_argument("-b", "--branch", required=False, default="master", help="git branch name to create tarball from [master]") +parser.add_argument("-f", "--force-tag", required=False, action="store_true", help="force tag (replace git tag if it already exists)") +parser.add_argument("-s", "--skip-checks", required=False, action="store_true", help="skip checks (that local and remote repos are in sync)") +parser.add_argument("-u", "--username", required=False, help="SourceForge username (upload to SourceForge will be skipped if not provided)") +args = parser.parse_args() -print "Looking for rsync" +version = args.version +branch = args.branch +dirname = "swig-" + version +force_tag = args.force_tag +skip_checks = args.skip_checks +username = args.username + +print("Looking for rsync") os.system("which rsync") and failed("rsync not installed/found. Please install.") -print "Making source tarball" -os.system("python ./mkdist.py " + version + " " + branch) and failed("") +print("Making source tarball") +force = "--force-tag" if force_tag else "" +skip = "--skip-checks" if skip_checks else "" +os.system("python ./mkdist.py {} {} --branch {} {}".format(force, skip, branch, version)) and failed("") -print "Build Windows package" +print("Build Windows package") os.system("./mkwindows.sh " + version) and failed("") -print "Uploading to SourceForge" +if username: + print("Uploading to SourceForge") -swig_dir_sf = username + ",swig@frs.sourceforge.net:/home/frs/project/s/sw/swig/swig/swig-" + version + "/" -swigwin_dir_sf = username + ",swig@frs.sourceforge.net:/home/frs/project/s/sw/swig/swigwin/swigwin-" + version + "/" + swig_dir_sf = username + ",swig@frs.sourceforge.net:/home/frs/project/s/sw/swig/swig/swig-" + version + "/" + swigwin_dir_sf = username + ",swig@frs.sourceforge.net:/home/frs/project/s/sw/swig/swigwin/swigwin-" + version + "/" -# If a file with 'readme' in the name exists in the same folder as the zip/tarball, it gets automatically displayed as the release notes by SF -full_readme_file = "readme-" + version + ".txt" -os.system("rm -f " + full_readme_file) -os.system("cat swig-" + version + "/README " + "swig-" + version + "/CHANGES.current " + "swig-" + version + "/RELEASENOTES " + "> " + full_readme_file) + # If a file with 'readme' in the name exists in the same folder as the zip/tarball, it gets automatically displayed as the release notes by SF + full_readme_file = "readme-" + version + ".txt" + os.system("rm -f " + full_readme_file) + os.system("cat swig-" + version + "/README " + "swig-" + version + "/CHANGES.current " + "swig-" + version + "/RELEASENOTES " + "> " + full_readme_file) -os.system("rsync --archive --verbose -P --times -e ssh " + "swig-" + version + ".tar.gz " + full_readme_file + " " + swig_dir_sf) and failed("") -os.system("rsync --archive --verbose -P --times -e ssh " + "swigwin-" + version + ".zip " + full_readme_file + " " + swigwin_dir_sf) and failed("") + os.system("rsync --archive --verbose -P --times -e ssh " + "swig-" + version + ".tar.gz " + full_readme_file + " " + swig_dir_sf) and failed("") + os.system("rsync --archive --verbose -P --times -e ssh " + "swigwin-" + version + ".zip " + full_readme_file + " " + swigwin_dir_sf) and failed("") -print "Finished" + print("Finished") -print "Now log in to SourceForge and set the operating systems applicable to the newly uploaded tarball and zip file. Also remember to do a 'git push --tags'." + print("Now log in to SourceForge and set the operating systems applicable to the newly uploaded tarball and zip file. Also remember to do a 'git push --tags'.") diff --git a/Tools/mkwindows.sh b/Tools/mkwindows.sh index 0651bbd60..e6ae84350 100755 --- a/Tools/mkwindows.sh +++ b/Tools/mkwindows.sh @@ -9,6 +9,8 @@ # path to zip program zip= +wine= + # options for configure extraconfigureoptions= compileflags="-O2 -Wall -Wextra" @@ -41,6 +43,11 @@ else echo "Building native Windows executable on Linux" if test x$zip = x; then zip=zip + wine=$(which wine) + fi + if test x$wine = x; then + echo "Could not detect wine - please install wine-stable package." + exit 1; fi echo "Checking that mingw 32-bit gcc is installed/available" if test -n "`which i686-w64-mingw32-gcc`" ; then @@ -109,9 +116,9 @@ if test -f "$tarball"; then echo "Compiling (quietly)..." make > build.log echo "Simple check to see if swig.exe runs..." - env LD_LIBRARY_PATH= PATH= ./swig.exe -version || exit 1 + env LD_LIBRARY_PATH= PATH= $wine ./swig.exe -version || exit 1 echo "Simple check to see if ccache-swig.exe runs..." - env LD_LIBRARY_PATH= PATH= ./CCache/ccache-swig.exe -V || exit 1 + env LD_LIBRARY_PATH= PATH= $wine ./CCache/ccache-swig.exe -V || exit 1 echo "Creating $swigwinbasename.zip..." cd .. cp $swigbasename/swig.exe $swigwinbasename diff --git a/Tools/nuget-install.cmd b/Tools/nuget-install.cmd index 08caea7e0..eec7f8787 100644 --- a/Tools/nuget-install.cmd +++ b/Tools/nuget-install.cmd @@ -1,5 +1,4 @@ rem Workaround 'nuget install' not being reliable by retrying a few times - @echo off rem initiate the retry number set errorCode=1 @@ -13,6 +12,7 @@ rem problem? IF ERRORLEVEL %errorCode% GOTO :RETRY rem everything is fine! +@echo Installed nuget, retries: %reTryNumber% GOTO :EXIT :RETRY diff --git a/Tools/obs-buildlogs.py b/Tools/obs-buildlogs.py index eaf0f613b..1c77e80c4 100755 --- a/Tools/obs-buildlogs.py +++ b/Tools/obs-buildlogs.py @@ -11,11 +11,11 @@ def remove_old_files(): os.remove(file) def download(): - repos = subprocess.Popen(['osc', 'repositories'], stdout=subprocess.PIPE) + repos = subprocess.Popen(["osc", "repositories"], stdout=subprocess.PIPE) for line in repos.stdout: - command = ['osc', 'buildlog', '--last'] + line.split() + command = ["osc", "buildlog", "--last"] + line.split() filename = "-".join(line.split()) + ".log" - print "Downloading logs using: {}".format(" ".join(command)) + print("Downloading logs using: {}".format(" ".join(command))) buildlog = subprocess.Popen(command, stdout=subprocess.PIPE) print("Writing log to {}".format(filename)) diff --git a/Tools/swig.gdb b/Tools/swig.gdb index 61872c5d6..5a652cae8 100644 --- a/Tools/swig.gdb +++ b/Tools/swig.gdb @@ -15,7 +15,7 @@ define swigprint else set $expand_count = -1 end - Printf "%s\n", Swig_to_string($arg0, $expand_count) + printf "%s\n", Swig_to_string($arg0, $expand_count) end document swigprint Displays any SWIG DOH object @@ -31,7 +31,7 @@ define locswigprint else set $expand_count = -1 end - Printf "%s\n", Swig_to_string_with_location($arg0, $expand_count) + printf "%s\n", Swig_to_string_with_location($arg0, $expand_count) end document locswigprint Displays any SWIG DOH object prefixed with file and line location diff --git a/Tools/testflags.py b/Tools/testflags.py index 981e8d59a..f3d216b59 100755 --- a/Tools/testflags.py +++ b/Tools/testflags.py @@ -12,6 +12,8 @@ def get_cflags(language, std, compiler): "java":"-Werror " + c_common, "javascript":"-Werror " + c_common, "lua":"-Werror " + c_common, + "mzscheme":"-Werror " + c_common, + "ocaml":"-Werror " + c_common, "octave":"-Werror " + c_common, "perl5":"-Werror " + c_common, "php":"-Werror " + c_common, @@ -21,7 +23,7 @@ def get_cflags(language, std, compiler): "scilab":"-Werror " + c_common, "tcl":"-Werror " + c_common, } - if compiler == 'clang': + if compiler == "clang": cflags["guile"] += " -Wno-attributes" # -Wno-attributes is for clang LLVM 3.5 and bdw-gc < 7.5 used by guile if language not in cflags: @@ -41,16 +43,18 @@ def get_cxxflags(language, std, compiler): "java":"-Werror " + cxx_common, "javascript":"-Werror " + cxx_common + " -Wno-error=unused-function", # Until overload_rename is fixed for node "lua":"-Werror " + cxx_common, + "mzscheme":"-Werror " + cxx_common, + "ocaml":"-Werror " + cxx_common, "octave":"-Werror " + cxx_common, "perl5":"-Werror " + cxx_common, "php":"-Werror " + cxx_common, "python":"-Werror " + cxx_common, "r":"-Werror " + cxx_common, - "ruby":"-Werror " + cxx_common, + "ruby":"-Werror " + cxx_common + " -Wno-deprecated-declarations", # For Ruby on MacOS Xcode 9.4 misconfiguration defining 'isfinite' to deprecated 'finite' "scilab":"-Werror " + cxx_common, "tcl":"-Werror " + cxx_common, } - if compiler == 'clang': + if compiler == "clang": cxxflags["guile"] += " -Wno-attributes" # -Wno-attributes is for clang LLVM 3.5 and bdw-gc < 7.5 used by guile if language not in cxxflags: @@ -60,12 +64,12 @@ def get_cxxflags(language, std, compiler): import argparse parser = argparse.ArgumentParser(description="Display CFLAGS or CXXFLAGS to use for testing the SWIG examples and test-suite.") -parser.add_argument('-l', '--language', required=True, help='set language to show flags for') +parser.add_argument("-l", "--language", required=True, help="set language to show flags for") flags = parser.add_mutually_exclusive_group(required=True) -flags.add_argument('-c', '--cflags', action='store_true', default=False, help='show CFLAGS') -flags.add_argument('-x', '--cxxflags', action='store_true', default=False, help='show CXXFLAGS') -parser.add_argument('-s', '--std', required=False, help='language standard flags for the -std= option') -parser.add_argument('-C', '--compiler', required=False, help='compiler used (clang or gcc)') +flags.add_argument("-c", "--cflags", action="store_true", default=False, help="show CFLAGS") +flags.add_argument("-x", "--cxxflags", action="store_true", default=False, help="show CXXFLAGS") +parser.add_argument("-s", "--std", required=False, help="language standard flags for the -std= option") +parser.add_argument("-C", "--compiler", required=False, help="compiler used (clang or gcc)") args = parser.parse_args() if args.cflags: diff --git a/Tools/travis-linux-install.sh b/Tools/travis-linux-install.sh index 50ac5cd09..37ef841dd 100755 --- a/Tools/travis-linux-install.sh +++ b/Tools/travis-linux-install.sh @@ -1,110 +1,128 @@ #!/bin/bash -set -e # exit on failure +# Install Linux packages where the version has been overidden in .travis.yml + +set -e # exit on failure (same as -o errexit) lsb_release -a -sudo apt-get -qq update +travis_retry sudo apt-get -qq update -if [[ "$CC" == gcc-5 ]]; then - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - sudo apt-get -qq update - sudo apt-get install -qq g++-5 -elif [[ "$CC" == gcc-6 ]]; then - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - sudo apt-get -qq update - sudo apt-get install -qq g++-6 +if [[ -n "$GCC" ]]; then + travis_retry sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + travis_retry sudo apt-get -qq update + travis_retry sudo apt-get install -qq g++-$GCC fi -sudo apt-get -qq install libboost-dev +travis_retry sudo apt-get -qq install libboost-dev WITHLANG=$SWIGLANG case "$SWIGLANG" in "") ;; "csharp") - sudo apt-get -qq install mono-devel + travis_retry sudo apt-get -qq install mono-devel ;; "d") - wget http://downloads.dlang.org/releases/2014/dmd_2.066.0-0_amd64.deb - sudo dpkg -i dmd_2.066.0-0_amd64.deb + travis_retry wget http://downloads.dlang.org/releases/2014/dmd_2.066.0-0_amd64.deb + travis_retry sudo dpkg -i dmd_2.066.0-0_amd64.deb ;; "go") + if [[ "$VER" ]]; then + eval "$(gimme ${VER}.x)" + fi ;; "javascript") case "$ENGINE" in "node") - sudo add-apt-repository -y ppa:chris-lea/node.js - sudo apt-get -qq update - sudo apt-get install -qq nodejs rlwrap - sudo npm install -g node-gyp + travis_retry wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.10/install.sh | bash + export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + travis_retry nvm install ${VER} + nvm use ${VER} + if [ "$VER" == "0.10" ] || [ "$VER" == "0.12" ] || [ "$VER" == "4" ] ; then +# travis_retry sudo apt-get install -qq nodejs node-gyp + travis_retry npm install -g node-gyp@$VER + else + travis_retry npm install -g node-gyp + fi ;; "jsc") - sudo apt-get install -qq libwebkitgtk-dev + travis_retry sudo apt-get install -qq libwebkitgtk-dev ;; "v8") - sudo apt-get install -qq libv8-dev + travis_retry sudo apt-get install -qq libv8-dev ;; esac ;; "guile") - sudo apt-get -qq install guile-2.0-dev + travis_retry sudo apt-get -qq install guile-2.0-dev ;; "lua") if [[ -z "$VER" ]]; then - sudo apt-get -qq install lua5.1 liblua5.1-dev + travis_retry sudo apt-get -qq install lua5.2 liblua5.2-dev else - sudo add-apt-repository -y ppa:ubuntu-cloud-archive/mitaka-staging - sudo apt-get -qq update - sudo apt-get -qq install lua${VER} liblua${VER}-dev + travis_retry sudo apt-get -qq install lua${VER} liblua${VER}-dev fi ;; + "mzscheme") + travis_retry sudo apt-get -qq install racket + ;; "ocaml") - # configure also looks for ocamldlgen, but this isn't packaged. But it isn't used by default so this doesn't matter. - sudo apt-get -qq install ocaml ocaml-findlib + travis_retry sudo apt-get -qq install ocaml camlp4 ;; "octave") if [[ -z "$VER" ]]; then - sudo apt-get -qq install octave3.2 octave3.2-headers + travis_retry sudo apt-get -qq install liboctave-dev else - sudo add-apt-repository -y ppa:kwwette/octaves - sudo apt-get -qq update - sudo apt-get -qq install liboctave${VER}-dev + # Travis adds external PPAs which contain newer versions of packages + # than in baseline trusty. These newer packages prevent some of the + # Octave packages in ppa:kwwette/octave, which rely on the older + # packages in trusty, from installing. To prevent these kind of + # interactions arising, clean out all external PPAs added by Travis + # before installing Octave + sudo rm -rf /etc/apt/sources.list.d/* + travis_retry sudo apt-get -qq update + travis_retry sudo add-apt-repository -y ppa:kwwette/octaves + travis_retry sudo apt-get -qq update + travis_retry sudo apt-get -qq install liboctave${VER}-dev fi ;; "php") - sudo apt-get install php5-cli php5-dev + travis_retry sudo add-apt-repository -y ppa:ondrej/php + travis_retry sudo apt-get -qq update + travis_retry sudo apt-get -qq install php$VER-cli php$VER-dev ;; "python") - git clone https://github.com/jcrocholl/pep8.git - ( - cd pep8 - git checkout tags/1.5.7 - python ./setup.py build - sudo python ./setup.py install - ) + pip install --user pycodestyle if [[ "$PY3" ]]; then - sudo apt-get install -qq python3-dev + travis_retry sudo apt-get install -qq python3-dev fi WITHLANG=$SWIGLANG$PY3 if [[ "$VER" ]]; then - sudo add-apt-repository -y ppa:fkrull/deadsnakes - sudo apt-get -qq update - sudo apt-get -qq install python${VER}-dev + travis_retry sudo add-apt-repository -y ppa:deadsnakes/ppa + travis_retry sudo apt-get -qq update + travis_retry sudo apt-get -qq install python${VER}-dev WITHLANG=$SWIGLANG$PY3=$SWIGLANG$VER fi ;; "r") - sudo apt-get -qq install r-base + travis_retry sudo apt-get -qq install r-base ;; "ruby") if [[ "$VER" ]]; then - rvm install $VER + travis_retry rvm install $VER fi ;; "scilab") - sudo apt-get -qq install scilab + # Travis has the wrong version of Java pre-installed resulting in error using scilab: + # /usr/bin/scilab-bin: error while loading shared libraries: libjava.so: cannot open shared object file: No such file or directory + echo "JAVA_HOME was set to $JAVA_HOME" + unset JAVA_HOME + travis_retry sudo apt-get -qq install scilab ;; "tcl") - sudo apt-get -qq install tcl8.4-dev + travis_retry sudo apt-get -qq install tcl-dev ;; esac + +set +e # turn off exit on failure (same as +o errexit) diff --git a/Tools/travis-osx-install.sh b/Tools/travis-osx-install.sh index 965deed42..393d96e60 100755 --- a/Tools/travis-osx-install.sh +++ b/Tools/travis-osx-install.sh @@ -1,30 +1,34 @@ #!/bin/bash -set -e # exit on failure +# Install MacOS packages where the version has been overidden in .travis.yml + +set -e # exit on failure (same as -o errexit) sw_vers -brew update -brew list -brew install pcre -# brew install boost +travis_retry brew update +travis_retry brew list +# travis_retry brew install pcre # Travis Xcode-7.3 has pcre +# travis_retry brew install boost WITHLANG=$SWIGLANG case "$SWIGLANG" in "csharp") - brew install https://s3.amazonaws.com/travisbuilds.swig.org/mono.rb + travis_retry brew install mono ;; "guile") - Tools/brew-install guile + travis_retry Tools/brew-install guile ;; "lua") - brew install lua + travis_retry brew install lua + ;; + "octave") + travis_retry brew install octave ;; "python") WITHLANG=$SWIGLANG$PY3 - if [[ "$PY3" ]]; then - brew install python3 - brew list -v python3 - fi ;; esac + +# Workaround for https://github.com/travis-ci/travis-ci/issues/6522 +set +e # turn off exit on failure (same as +o errexit) diff --git a/appveyor.yml b/appveyor.yml index 9f2068903..42eaa36f4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,76 +3,127 @@ platform: - x64 environment: + global: + MAKEJOBS: 2 + matrix: - SWIGLANG: csharp - VSVER: 14 + VSVER: 12 - SWIGLANG: csharp - VSVER: 12 + VSVER: 14 - SWIGLANG: java - VSVER: 12 + VSVER: 14 - SWIGLANG: python - VSVER: 12 + VSVER: 14 VER: 27 - SWIGLANG: python - VSVER: 12 - VER: 35 - PY3: 1 + VSVER: 14 + VER: 36 + PY3: 3 + - SWIGLANG: python + OSVARIANT: cygwin + - SWIGLANG: python + OSVARIANT: mingw + VER: 27 + - SWIGLANG: python + OSVARIANT: mingw + WITHLANG: python + VER: 37 + PY3: 3 install: - date /T & time /T -- set PATH=C:\cygwin\bin;%PATH% -- set CYGWIN=nodosfilewarning -- git clone -q --depth=1 --single-branch --branch cccl-1.0 git://github.com/swig/cccl.git C:\cccl-1.0 -- bash -c "cp C:/cccl-1.0/cccl /usr/bin" - ps: >- - If ($env:Platform -Match "x86") { + if ($env:Platform -eq "x86") { $env:PCRE_PLATFORM="Win32" $env:JAVA_HOME="C:/Program Files (x86)/Java/jdk1.8.0" $env:VCVARS_PLATFORM="x86" $env:LANG_PLATFORM="" - } Else { + $env:CYGWINBIN="C:\cygwin\bin" + $env:CYGWINSETUP="C:/cygwin/setup-x86.exe" + $env:MSYSBIN="C:\msys64\usr\bin" + $env:MINGWBIN="C:\msys64\mingw32\bin" + $env:MBITS="32" + $env:MARCH="i686" + } else { $env:PCRE_PLATFORM="x64" $env:JAVA_HOME="C:/Program Files/Java/jdk1.8.0" $env:VCVARS_PLATFORM="amd64" $env:LANG_PLATFORM="-x64" + $env:CYGWINBIN="C:\cygwin64\bin" + $env:CYGWINSETUP="C:/cygwin64/setup-x86_64.exe" + $env:MSYSBIN="C:\msys64\usr\bin" + $env:MINGWBIN="C:\msys64\mingw64\bin" + $env:MBITS="64" + $env:MARCH="x86_64" } -- ps: $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS")) -- echo "Using Visual Studio %VSVER%.0 at %VSCOMNTOOLS%" -- call "%VSCOMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM% -- Tools\nuget-install.cmd pcre -Verbosity detailed -Version 8.33.0.1 -OutputDirectory C:\pcre -- set PCRE_ROOT=C:/pcre/pcre.8.33.0.1/build/native -- set PATH=C:\Python%VER%%LANG_PLATFORM%;%PATH% -- python -V +- ps: >- + if (!$env:OSVARIANT) { + $env:PATH="$env:CYGWINBIN;$env:PATH" + $env:CYGWIN="nodosfilewarning" + $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS")) + $env:CC="cccl" + $env:CXX="cccl" + } elseif ($env:OSVARIANT -eq "cygwin") { + $env:PATH="$env:CYGWINBIN;$env:PATH" + $env:CYGWIN="nodosfilewarning" + $env:CC="gcc" + $env:CXX="g++" + } elseif ($env:OSVARIANT -eq "mingw") { + # Note mingw setup tests the native Windows Python distribution (not MinGW Python) with gcc + $env:PATH="$env:MINGWBIN;$env:MSYSBIN;$env:PATH" + $env:MSYSTEM="MINGW$env:MBITS" # This is important for msys2 + $env:CC="gcc" + $env:CXX="g++" + if ($env:MBITS -eq "64" -and $env:SWIGLANG -eq "python") { + $env:CHECK_OPTIONS2="CFLAGS+=-DMS_WIN64 CXXFLAGS+=-DMS_WIN64" + } + } +- if "%OSVARIANT%"=="" bash -c "cd /usr/bin && curl --retry 15 -s -L https://github.com/swig/cccl/archive/cccl-1.0.tar.gz | tar -xz --strip 1 cccl-cccl-1.0/cccl" +- if "%OSVARIANT%"=="" echo Using Visual Studio %VSVER%.0 at %VSCOMNTOOLS% +- if "%OSVARIANT%"=="" call "%VSCOMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM% +- if "%OSVARIANT%"=="" Tools\nuget-install.cmd pcre -Verbosity quiet -Version 8.33.0.1 -OutputDirectory C:\pcre +- if "%OSVARIANT%"=="" set PCRE_ROOT=C:/pcre/pcre.8.33.0.1/build/native +- if not "%OSVARIANT%"=="cygwin" set PATH=C:\Python%VER%%LANG_PLATFORM%;%PATH% +- if "%OSVARIANT%"=="" bash -c "which cl.exe" +- if "%OSVARIANT%"=="" bash -c "cl.exe /? 2>&1 | head -n 1" +- if "%OSVARIANT%"=="" bash -c "which csc.exe" +- if "%OSVARIANT%"=="" bash -c "csc.exe /? | head -n 1" +- if "%OSVARIANT%"=="cygwin" %CYGWINSETUP% --quiet-mode --packages python2-devel,libpcre-devel,libboost-devel > cygwin-install.txt || bash -c "cat cygwin-install.txt" +- if "%OSVARIANT%"=="mingw" bash -c "pacman --noconfirm --sync mingw%MBITS%/mingw-w64-%MARCH%-pcre mingw%MBITS%/mingw-w64-%MARCH%-boost" +- if not "%WITHLANG%"=="" set SWIGWITHLANG==%WITHLANG% +- if not "%WITHLANG%"=="" where %WITHLANG% +- bash -c "which $CC" +- bash -c "which $CXX" +- bash -c "$CC --version | head -n 1" +- bash -c "$CXX --version | head -n 1" - bash -c "which python" - bash -c "python -V" -- bash -c "which cl.exe" -- bash -c "cl.exe /? 2>&1 | head -n 2" -- bash -c "which csc.exe" -- bash -c "csc.exe /? | head -n 2" -- bash -c "which cccl" -- bash -c "cccl --version" -- make --version +- bash -c "make --version | head -n 2" +- pwd +- echo MAKEJOBS=%MAKEJOBS% - uname -a build_script: -- set CCCL_OPTIONS=--cccl-muffle /W3 +- set CCCL_OPTIONS=--cccl-muffle /W3 /EHsc - set CHECK_OPTIONS=CSHARPOPTIONS=-platform:%Platform% # Open dummy file descriptor to fix error on cygwin: ./configure: line 560: 0: Bad file descriptor -- bash -c "exec 0- - If ("$env:SWIGLANG$env:VER" -Match "python27") { - $env:CCCL_OPTIONS="$env:CCCL_OPTIONS /wd4717" - } - .\swig.exe -version +- if not "%OSVARIANT%"=="" CCache\ccache-swig -V - bash -c "file ./swig.exe" -- bash -c "time make -k check-%SWIGLANG%-version" -- bash -c "time make -k check-%SWIGLANG%-examples %CHECK_OPTIONS%" -- bash -c "time make -k check-%SWIGLANG%-test-suite %CHECK_OPTIONS%" +- bash -c "make check-%SWIGLANG%-version" +- bash -c "make check-%SWIGLANG%-enabled" +- bash -c "time make -k check-%SWIGLANG%-examples %CHECK_OPTIONS% %CHECK_OPTIONS2%" +- bash -c "time make -k check-%SWIGLANG%-test-suite -j%MAKEJOBS% %CHECK_OPTIONS% %CHECK_OPTIONS2%" # Do not build on tags (GitHub only) skip_tags: true + +#on_finish: # Display RDP connection information +# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/configure.ac b/configure.ac index 54b20e9ec..a9bc5d5ce 100644 --- a/configure.ac +++ b/configure.ac @@ -2,11 +2,8 @@ dnl Process this file with autoconf to produce a configure script. dnl The macros which aren't shipped with the autotools are stored in the dnl Tools/config directory in .m4 files. -AC_INIT([swig],[3.0.11],[http://www.swig.org]) - -dnl NB: When this requirement is increased to 2.60 or later, AC_PROG_SED -dnl definition below can be removed -AC_PREREQ(2.58) +AC_INIT([swig],[4.0.1],[http://www.swig.org]) +AC_PREREQ(2.60) AC_CONFIG_SRCDIR([Source/Swig/swig.h]) AC_CONFIG_AUX_DIR([Tools/config]) @@ -16,9 +13,6 @@ AM_INIT_AUTOMAKE dnl Some extra defines for the config file AH_BOTTOM([ -/* Default language */ -#define SWIG_LANG "-tcl" - /* Deal with attempt by Microsoft to deprecate C standard runtime functions */ #if defined(_MSC_VER) # define _CRT_SECURE_NO_DEPRECATE @@ -28,8 +22,6 @@ AH_BOTTOM([ dnl Check for programs that a user requires to build SWIG AC_PROG_CC AC_PROG_CXX -AC_EXEEXT -AC_OBJEXT AM_PROG_CC_C_O # Needed for subdir-objects in AUTOMAKE_OPTIONS AC_COMPILE_WARNINGS # Increase warning levels @@ -49,11 +41,6 @@ AC_CHECK_FUNC(popen, AC_DEFINE(HAVE_POPEN, 1, [Define if popen is available]), A fi dnl PCRE - -dnl AX_PATH_GENERIC() relies on AC_PROG_SED() but it is defined only in -dnl autoconf 2.60 so trivially predefine it ourselves for the older versions -m4_ifdef([AC_PROG_SED],, [AC_DEFUN([AC_PROG_SED], [AC_PATH_PROG([SED], sed)])]) - AC_ARG_WITH([pcre], [AS_HELP_STRING([--without-pcre], [Disable support for regular expressions using PCRE])], @@ -188,19 +175,19 @@ then if test "$with_next_framework" ; then LDSHARED="$LDSHARED \$(LDLIBRARY)" fi ;; - *-*-linux*) LDSHARED="gcc -shared";; + *-*-linux*) LDSHARED="$CC -shared";; *-*-dgux*) LDSHARED="ld -G";; - *-*-freebsd3*) LDSHARED="gcc -shared";; + *-*-freebsd3*) LDSHARED="$CC -shared";; *-*-freebsd* | *-*-openbsd*) LDSHARED="ld -Bshareable";; *-*-netbsd*) if [[ "`$CC -dM -E - /dev/null` \ - `ls -d -r /usr/lib*/tcl*/ 2>/dev/null` \ - `ls -d -r /usr/local/lib*/ 2>/dev/null` \ - `ls -d -r /usr/local/lib*/tcl*/ 2>/dev/null` ; do - if test -f $i"tclConfig.sh" ; then - TCLCONFIG=`(cd $i; pwd)` - break - fi + for d in $dirs ; do + for i in `ls -d -r $d 2>/dev/null` ; do + if test -f $i"tclConfig.sh" ; then + TCLCONFIG=`(cd $i; pwd)` + break + fi done + done fi if test x"${TCLCONFIG}" = x ; then AC_MSG_RESULT(no) @@ -598,7 +592,7 @@ if test x"${PYBIN}" = xno; then else # First figure out the name of the Python executable if test "x$PYBIN" = xyes; then - AC_CHECK_PROGS(PYTHON, [python python2.8 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) + AC_CHECK_PROGS(PYTHON, [python python2.7]) else PYTHON="$PYBIN" fi @@ -612,8 +606,11 @@ else PYVER=0 else AC_MSG_CHECKING(for Python os.name) - PYOSNAME=`($PYTHON -c "import sys, os; sys.stdout.write(os.name)")` + PYOSNAME=`($PYTHON -c "import sys, os; sys.stdout.write(os.name)") 2>/dev/null` AC_MSG_RESULT($PYOSNAME) + AC_MSG_CHECKING(for Python path separator) + PYSEPARATOR=`($PYTHON -c "import sys, os; sys.stdout.write(os.sep)") 2>/dev/null` + AC_MSG_RESULT($PYSEPARATOR) fi fi @@ -625,8 +622,8 @@ else PYEPREFIX=`($PYTHON -c "import sys; sys.stdout.write(sys.exec_prefix)") 2>/dev/null` AC_MSG_RESULT($PYEPREFIX) - if test x"$PYOSNAME" = x"nt"; then - # Windows installations are quite different to posix installations + if test x"$PYOSNAME" = x"nt" -a x"$PYSEPARATOR" = x"\\"; then + # Windows installations are quite different to posix installations (MinGW path separator is a forward slash) PYPREFIX=`echo "$PYPREFIX" | sed -e 's,\\\\,/,g'` # Forward slashes are easier to use and even work on Windows most of the time PYTHON_SO=.pyd @@ -654,7 +651,7 @@ else # Need to do this hack since autoconf replaces __file__ with the name of the configure file filehack="file__" - PYVERSION=`($PYTHON -c "import sys,string,operator,os.path; sys.stdout.write(operator.getitem(os.path.split(operator.getitem(os.path.split(string.__$filehack),0)),1))")` + PYVERSION=`($PYTHON -c "import sys,string,operator,os.path; sys.stdout.write(operator.getitem(os.path.split(operator.getitem(os.path.split(string.__$filehack),0)),1))") 2>/dev/null` AC_MSG_RESULT($PYVERSION) # Find the directory for libraries this is necessary to deal with @@ -742,10 +739,10 @@ else PYVER=0 fi if test "x$PY3BIN" = xyes; then - if test x"$PYOSNAME" = x"nt" -a $PYVER -ge 3; then + if test x"$PYOSNAME" = x"nt" -a x"$PYSEPARATOR" = x"\\" -a $PYVER -ge 3; then PYTHON3="$PYTHON" else - for py_ver in 3 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0 ""; do + for py_ver in 3 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 ""; do AC_CHECK_PROGS(PYTHON3, [python$py_ver]) if test -n "$PYTHON3"; then AC_CHECK_PROGS(PY3CONFIG, [$PYTHON3-config]) @@ -771,10 +768,13 @@ else if test $PYVER -ge 3; then AC_MSG_CHECKING(for Python 3.x os.name) - PY3OSNAME=`($PYTHON3 -c "import sys, os; sys.stdout.write(os.name)")` + PY3OSNAME=`($PYTHON3 -c "import sys, os; sys.stdout.write(os.name)") 2>/dev/null` AC_MSG_RESULT($PY3OSNAME) + AC_MSG_CHECKING(for Python 3.x path separator) + PYSEPARATOR=`($PYTHON3 -c "import sys, os; sys.stdout.write(os.sep)") 2>/dev/null` + AC_MSG_RESULT($PYSEPARATOR) - if test x"$PY3OSNAME" = x"nt"; then + if test x"$PY3OSNAME" = x"nt" -a x"$PYSEPARATOR" = x"\\"; then # Windows installations are quite different to posix installations # There is no python-config to use AC_MSG_CHECKING(for Python 3.x prefix) @@ -815,7 +815,8 @@ else PY3PREFIX=`($PY3CONFIG --prefix) 2>/dev/null` AC_MSG_RESULT($PY3PREFIX) AC_MSG_CHECKING(for Python 3.x exec-prefix) - PY3EPREFIX=`($PY3CONFIG --exec-prefix) 2>/dev/null` + # Piped through xargs to strip trailing whitespace (bug in msys2 + mingw Python) + PY3EPREFIX=`($PY3CONFIG --exec-prefix | xargs) 2>/dev/null` AC_MSG_RESULT($PY3EPREFIX) # Note: I could not think of a standard way to get the version string from different versions. @@ -825,7 +826,7 @@ else # Need to do this hack since autoconf replaces __file__ with the name of the configure file filehack="file__" - PY3VERSION=`($PYTHON3 -c "import string,operator,os.path; print(operator.getitem(os.path.split(operator.getitem(os.path.split(string.__$filehack),0)),1))")` + PY3VERSION=`($PYTHON3 -c "import string,operator,os.path; print(operator.getitem(os.path.split(operator.getitem(os.path.split(string.__$filehack),0)),1))") 2>/dev/null` AC_MSG_RESULT($PY3VERSION) # Find the directory for libraries this is necessary to deal with @@ -883,7 +884,39 @@ else AC_SUBST(PY3LIB) AC_SUBST(PY3LINK) AC_SUBST(PYTHON3DYNAMICLINKING) - AC_CHECK_PROGS(PEP8, pep8) +fi + +if test -n "$PYINCLUDE" || test -n "$PY3INCLUDE" ; then + AC_CHECK_PROGS(PYCODESTYLE, pycodestyle) + if test -n "$PYCODESTYLE"; then + AC_MSG_CHECKING(pycodestyle version) + pycodestyle_version=`$PYCODESTYLE --version 2>/dev/null` + AC_MSG_RESULT($pycodestyle_version) + fi +fi + +AC_ARG_WITH(2to3, AS_HELP_STRING([--with-2to3=path], [Set location of Python 2to3 tool]), [PY2TO3BIN="$withval"], [PY2TO3BIN="yes"]) +if test -n "$PYTHON3"; then + if test "x$PY2TO3BIN" = xyes; then + py3to2=`echo $PYTHON3 | sed -e "s/python/2to3-/"` + AC_CHECK_PROGS(PY2TO3, $py3to2 2to3) + if test -z "$PY2TO3"; then + # Windows distributions don't always have the 2to3 executable + AC_MSG_CHECKING(for 2to3.py) + py2to3script="$PY3PREFIX/Tools/scripts/2to3.py" + if test -f "$py2to3script"; then + AC_MSG_RESULT($py2to3script) + PY2TO3="$PYTHON3 $py2to3script" + else + AC_MSG_RESULT(Not found) + fi + fi + else + PY2TO3="$PY2TO3BIN" + fi + if test -z "$PY2TO3"; then + PYTHON3= + fi fi #---------------------------------------------------------------- @@ -1006,30 +1039,57 @@ OCTAVE_SO=.oct AC_ARG_WITH(octave, AS_HELP_STRING([--without-octave], [Disable Octave]) AS_HELP_STRING([--with-octave=path], [Set location of Octave executable]),[OCTAVEBIN="$withval"], [OCTAVEBIN="$alllang_default"]) -# First, check for "--without-octave" or "--with-octave=no". +# Check for "--without-octave" or "--with-octave=no". if test x"${OCTAVEBIN}" = xno; then AC_MSG_NOTICE([Disabling Octave]) OCTAVE= -# First figure out what the name of Octave is +# Check for Octave; prefer command-line program "octave-cli" to (in newer versions) GUI program "octave" elif test "x$OCTAVEBIN" = xyes; then - AC_PATH_PROG(OCTAVE, [octave]) + AC_PATH_PROG(OCTAVE, [octave-cli octave]) else OCTAVE="$OCTAVEBIN" fi +# Check if Octave works if test -n "$OCTAVE"; then - AC_MSG_CHECKING([for mkoctfile]) - mkoctfile="$(dirname $OCTAVE)/$(basename $OCTAVE | sed -e 's/octave/mkoctfile/')" - AS_IF([test -x "${mkoctfile}"],[ - AC_MSG_RESULT([${mkoctfile}]) + AC_MSG_CHECKING([if ${OCTAVE} works]) + AS_IF([test "x`${OCTAVE} --version 2>/dev/null | sed -n -e '1p' | sed -n -e '/Octave, version/p'`" != x],[ + AC_MSG_RESULT([yes]) ],[ - AC_MSG_RESULT([not found, disabling Octave]) + AC_MSG_NOTICE([no]) OCTAVE= ]) fi + +# Check for required Octave helper program "mkoctfile" if test -n "$OCTAVE"; then + AC_MSG_CHECKING([for mkoctfile]) + version_suffix=["`echo $OCTAVE | sed -e 's|.*\(-[0-9][0-9.]*\)$|\1|'`"] + case $version_suffix in + -*) ;; + *) version_suffix="" ;; + esac + octave_directory=`dirname $OCTAVE` + if test "$octave_directory" = "." ; then + mkoctfile="mkoctfile${version_suffix}" + else + mkoctfile="${octave_directory}/mkoctfile${version_suffix}" + fi + AC_MSG_RESULT([${mkoctfile}]) + AC_MSG_CHECKING([if ${mkoctfile} works]) + AS_IF([test "x`${mkoctfile} --version 2>/dev/null | sed -n -e '1p' | sed -n -e '/mkoctfile, version/p'`" != x],[ + AC_MSG_RESULT([yes]) + ],[ + AC_MSG_RESULT([no]) + OCTAVE= + ]) +fi + +# Check for Octave preprocessor/compiler/linker flags +if test -n "$OCTAVE"; then + AC_MSG_CHECKING([for Octave preprocessor flags]) OCTAVE_CPPFLAGS= for var in CPPFLAGS INCFLAGS ALL_CXXFLAGS; do @@ -1041,12 +1101,13 @@ if test -n "$OCTAVE"; then done done AC_MSG_RESULT([$OCTAVE_CPPFLAGS]) + AC_MSG_CHECKING([for Octave compiler flags]) OCTAVE_CXXFLAGS= - for var in ALL_CXXFLAGS; do + for var in CXX ALL_CXXFLAGS; do for flag in `env - ${mkoctfile} -p ${var}`; do case ${flag} in - -g*|-W*) OCTAVE_CXXFLAGS="${OCTAVE_CXXFLAGS} ${flag}";; + -std=*|-g*|-W*) OCTAVE_CXXFLAGS="${OCTAVE_CXXFLAGS} ${flag}";; *) ;; esac done @@ -1054,19 +1115,28 @@ if test -n "$OCTAVE"; then save_CXXFLAGS="${CXXFLAGS}" CXXFLAGS="-Werror -O0" AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],[]) + AC_LANG_PROGRAM([],[]) ],[ OCTAVE_CXXFLAGS="${OCTAVE_CXXFLAGS} -O0" ]) CXXFLAGS="${save_CXXFLAGS}" AC_MSG_RESULT([$OCTAVE_CXXFLAGS]) + AC_MSG_CHECKING([for Octave linker flags]) OCTAVE_LDFLAGS= - for var in RDYNAMIC_FLAG LFLAGS RLD_FLAG OCTAVE_LIBS LIBS; do + for var in OCTLIBDIR; do + OCTAVE_LDFLAGS="${OCTAVE_LDFLAGS} "-L`env - ${mkoctfile} -p ${var}` + done + for var in RDYNAMIC_FLAG RLD_FLAG OCTAVE_LIBS LIBS; do OCTAVE_LDFLAGS="${OCTAVE_LDFLAGS} "`env - ${mkoctfile} -p ${var}` done AC_MSG_RESULT([$OCTAVE_LDFLAGS]) - for octave_opt in --silent --norc --no-history --no-window-system; do + +fi + +# Check for Octave options +if test -n "$OCTAVE"; then + for octave_opt in --no-window-system --silent --norc --no-history; do AC_MSG_CHECKING([if Octave option '${octave_opt}' is supported]) octave_out=`${OCTAVE} ${octave_opt} /dev/null 2>&1 | sed -n '1p' | sed -n '/unrecognized/p'` AS_IF([test "x${octave_out}" = x],[ @@ -1195,11 +1265,14 @@ case $host in if test -n "$JAVA_HOME"; then JAVA_HOME=`cygpath --mixed "$JAVA_HOME"` fi + dnl Java uses semicolons and not colons as separators in its classes search path under Windows. + JAVA_CLASSPATH_SEP=";" ;; *-*-mingw*) if test -n "$JAVA_HOME"; then JAVA_HOME=`${srcdir}/Tools/convertpath -u "$JAVA_HOME"` fi + JAVA_CLASSPATH_SEP=";" ;; *-*-darwin*) dnl Under OS X JAVA_HOME is not set by default, try to use the system default JRE. @@ -1212,6 +1285,11 @@ case $host in if test -r "$JAVA_OSX_STD_INCDIR/jni.h"; then JAVA_HOME_INCDIR=$JAVA_OSX_STD_INCDIR fi + JAVA_CLASSPATH_SEP=":" + ;; + *) + dnl Assume generic Unix. + JAVA_CLASSPATH_SEP=":" ;; esac @@ -1292,6 +1370,7 @@ if test -z "$JAVAINCDIR" ; then if test -r "$d/jni.h" ; then JAVAINCDIR=$d JAVAINC=-I\"$d\" + JAVA_HOME_MAYBE="`dirname $d`" break fi done @@ -1318,6 +1397,26 @@ else fi fi +# Auto-detecting JAVA_HOME is not so easy, below will only work up to and including jdk8 +if test -z "$JAVA_HOME" && test -n "$JAVA_HOME_MAYBE" ; then + AC_MSG_CHECKING(for java jdk from jni include paths) + if test -r "$JAVA_HOME_MAYBE/lib/tools.jar" ; then + JAVA_HOME=$JAVA_HOME_MAYBE + AC_MSG_RESULT([$JAVA_HOME]) + else + AC_MSG_RESULT(not found) + fi +fi + +# Javadoc support required for the Java test-suite is available by default in jdk9+ and in tools.jar in earlier jdk versions +AC_MSG_CHECKING(for java tools.jar) +if test -n "$JAVA_HOME" && test -r "$JAVA_HOME/lib/tools.jar" ; then + JAVA_TOOLS_JAR="$JAVA_HOME/lib/tools.jar" + AC_MSG_RESULT([$JAVA_TOOLS_JAR]) +else + AC_MSG_RESULT(not found) +fi + case $host in *-*-cygwin*) # TODO: Only use this flag if the compiler supports it, later versions of gcc no longer have it @@ -1383,6 +1482,8 @@ fi AC_SUBST(JAVA) AC_SUBST(JAVAC) AC_SUBST(JAVAINC) +AC_SUBST(JAVA_CLASSPATH_SEP) +AC_SUBST(JAVA_TOOLS_JAR) AC_SUBST(JAVADYNAMICLINKING) AC_SUBST(JAVALIBRARYPREFIX) AC_SUBST(JAVASO) @@ -1441,7 +1542,7 @@ else # check for include files AC_MSG_CHECKING(for JavaScriptCore/JavaScript.h) - AC_ARG_WITH(jscoreinc, [ --with-jscinc=path Set location of Javascript include directory], [JSCOREINCDIR="$withval"], [JSCOREINCDIR=]) + AC_ARG_WITH(jscoreinc, [ --with-jscoreinc=path Set location of Javascript include directory], [JSCOREINCDIR="$withval"], [JSCOREINCDIR=]) JSCOREVERSION= @@ -1475,7 +1576,7 @@ else fi # check for JavaScriptCore/Webkit libraries - AC_ARG_WITH(jscorelib,[ --with-jsclib=path Set location of the JavaScriptCore/Webkit library directory],[JSCORELIB="-L$withval"], [JSCORELIB=]) + AC_ARG_WITH(jscorelib,[ --with-jscorelib=path Set location of the JavaScriptCore/Webkit library directory],[JSCORELIB="-L$withval"], [JSCORELIB=]) if test -z "$JSCORELIB" -a -n "$PKGCONFIG"; then AC_MSG_CHECKING(for JavaScriptCore/Webkit library) @@ -1499,7 +1600,7 @@ else # check for include files AC_MSG_CHECKING(for V8 Javascript v8.h) - AC_ARG_WITH(jsv8inc, [ --with-jsv8inc=path Set location of Javascript v8 include directory], [JSV8INCDIR="$withval"]) + AC_ARG_WITH(jsv8inc, [ --with-jsv8inc=path Set location of Javascript v8 include directory], [JSV8INCDIR="$withval"], [JSV8INCDIR=]) # if not include dir is specified we try to find if test -z "$JSV8INCDIR"; then @@ -1582,34 +1683,6 @@ AC_SUBST(JSV8ENABLED) AC_SUBST(NODEJS) AC_SUBST(NODEGYP) -#---------------------------------------------------------------- -# Look for gcj -#---------------------------------------------------------------- - -AC_ARG_WITH(gcj, AS_HELP_STRING([--without-gcj], [Disable GCJ]) -AS_HELP_STRING([--with-gcj=path], [Set location of gcj executable]),[GCJBIN="$withval"], [GCJBIN="$alllang_default"]) -AC_ARG_WITH(gcjh, [ --with-gcjh=path Set location of gcjh executable],[GCJHBIN="$withval"], [GCJHBIN=]) - -# First, check for "--without-gcj" or "--with-gcj=no". -if test x"${GCJBIN}" = xno; then - AC_MSG_NOTICE([Disabling GCJ]) -else - if test "x$GCJBIN" = xyes; then - AC_CHECK_PROGS(GCJ, gcj) - else - GCJ="$GCJBIN" - fi - - if test -z "$GCJCBIN"; then - AC_CHECK_PROGS(GCJH, gcjh) - else - GCJH="$GCJHBIN" - fi -fi - -AC_SUBST(GCJ) -AC_SUBST(GCJH) - #---------------------------------------------------------------- # Look for Android #---------------------------------------------------------------- @@ -1681,17 +1754,28 @@ else fi if test -n "$GUILE_CONFIG" ; then if test x"$GUILE" = xyes; then - AC_MSG_CHECKING([for guile bindir]) - guile_bindir="`$GUILE_CONFIG info bindir`" - AC_MSG_RESULT([$guile_bindir]) - GUILE=$guile_bindir/guile + AC_MSG_CHECKING([for guile executable]) + # Try extracting it via guile-config first. If it's defined there it's the most reliable result + GUILE="`$GUILE_CONFIG info guile 2>/dev/null`" + if test -n "$GUILE"; then + AC_MSG_RESULT([$GUILE]) + else + AC_MSG_RESULT([not found via guile-config - constructing path]) + AC_MSG_CHECKING([for guile bindir]) + guile_bindir="`$GUILE_CONFIG info bindir`" + AC_MSG_RESULT([$guile_bindir]) + GUILE="$guile_bindir/guile" + fi if ! test -f "$GUILE" ; then - GUILE= + GUILE= AC_PATH_PROG(GUILE, guile) fi + if test -z "$GUILE" ; then + AC_MSG_WARN([no suitable guile executable found. Disabling Guile]) + fi fi - if test -f "$GUILE" ; then + if test -n "$GUILE" ; then AC_MSG_CHECKING([for guile version]) guile_version=`$GUILE -c '(display (effective-version))'` AC_MSG_RESULT([$guile_version]) @@ -1699,20 +1783,33 @@ else guile_good_version=`$GUILE -c '(if (>= (string->number (effective-version)) 1.8) (display "yes") (display "no"))'` AC_MSG_RESULT([$guile_good_version]) if test x"$guile_good_version" != xyes ; then + AC_MSG_WARN([at least guile version 1.8 is required. Disabling Guile]) GUILE= fi fi - if test -z "$GUILE_CFLAGS" ; then - AC_MSG_CHECKING([for guile compile flags]) - GUILE_CFLAGS="`$GUILE_CONFIG compile`" # Note that this can sometimes be empty - AC_MSG_RESULT([$GUILE_CFLAGS]) + if test -n "$GUILE" ; then + # Test if guile-config and guile versions match. They should. + gc_version="`$GUILE_CONFIG --version 2>&1 | sed '1 s/.* //;q'`" + g_version="`$GUILE --version | sed '1 s/.* //;q'`" + if test "$gc_version" != "$g_version"; then + AC_MSG_WARN([different versions reported by $GUILE_CONFIG ($gc_version) and $GUILE ($g_version). Disabling Guile]) + GUILE= + fi fi - if test -z "$GUILE_LIBS" ; then - AC_MSG_CHECKING([for guile link flags]) - GUILE_LIBS="`$GUILE_CONFIG link`" - AC_MSG_RESULT([$GUILE_LIBS]) + if test -n "$GUILE" ; then + if test -z "$GUILE_CFLAGS" ; then + AC_MSG_CHECKING([for guile compile flags]) + GUILE_CFLAGS="`$GUILE_CONFIG compile`" # Note that this can sometimes be empty + AC_MSG_RESULT([$GUILE_CFLAGS]) + fi + + if test -z "$GUILE_LIBS" ; then + AC_MSG_CHECKING([for guile link flags]) + GUILE_LIBS="`$GUILE_CONFIG link`" + AC_MSG_RESULT([$GUILE_LIBS]) + fi fi fi fi @@ -1896,7 +1993,7 @@ AC_SUBST(RUBYSO) AC_SUBST(RUBYDYNAMICLINKING) #------------------------------------------------------------------------- -# Look for PHP +# Look for PHP7 #------------------------------------------------------------------------- PHPBIN= @@ -1909,42 +2006,43 @@ if test x"${PHPBIN}" = xno; then AC_MSG_NOTICE([Disabling PHP]) PHP= else - if test "x$PHPBIN" = xyes; then - AC_CHECK_PROGS(PHP, [php5 php]) + AC_CHECK_PROGS(PHP, [php7.3 php7.2 php7.1 php7.0 php]) else PHP=$PHPBIN fi - AC_MSG_CHECKING(for PHP header files) - dnl /usr/bin/php5 -> /usr/bin/php-config5 - case $PHP in - *5) - PHPCONFIG=`echo "$PHP"|sed 's/5$/-config5/'` ;; - *) - PHPCONFIG=$PHP-config ;; - esac - php_version=`$PHPCONFIG --version 2>/dev/null` - case $php_version in - 5*) - PHPINC=`$PHPCONFIG --includes 2>/dev/null` - if test -n "$PHPINC"; then - AC_MSG_RESULT($PHPINC) - else - AC_MSG_RESULT(not found) - fi - ;; - "") + if test -n "$PHP"; then + AC_MSG_CHECKING(for PHP header files) + dnl /usr/bin/php7.0 -> /usr/bin/php-config7.0 + case $PHP in + *7.*) + PHPCONFIG=`echo "$PHP"|sed 's/7\...*$/-config&/'` ;; + *) + PHPCONFIG=$PHP-config ;; + esac + php_version=`$PHPCONFIG --version 2>/dev/null` + case $php_version in + 7.*) + PHPINC=`$PHPCONFIG --includes 2>/dev/null` + if test -n "$PHPINC"; then + AC_MSG_RESULT($PHPINC) + else + AC_MSG_RESULT(not found) + fi + ;; + "") AC_MSG_RESULT([could not find $PHPCONFIG or obtain PHP version from it]) ;; - *) - AC_MSG_RESULT([found PHP $php_version, but only PHP 5 is supported]) ;; - esac + *) + AC_MSG_RESULT([found PHP $php_version - not PHP 7]) ;; + esac + fi fi AC_SUBST(PHP) AC_SUBST(PHPINC) #---------------------------------------------------------------- -# Look for ocaml +# Look for OCaml #---------------------------------------------------------------- AC_ARG_WITH(ocaml, AS_HELP_STRING([--without-ocaml], [Disable OCaml]), [with_ocaml="$withval"], [with_ocaml="$alllang_default"]) @@ -1959,205 +2057,37 @@ if test x"${with_ocaml}" = xno; then AC_MSG_NOTICE([Disabling OCaml]) OCAMLC= else - AC_MSG_CHECKING(for Ocaml DL load generator) + # OCaml compiler + if test -z "$OCAMLC"; then + AC_CHECK_PROGS(OCAMLC, ocamlc) + fi + + # OCaml Pre-Processor-Pretty-Printer + if test -z "$CAMLP4"; then + AC_CHECK_PROGS(CAMLP4, camlp4) + fi + + # OCaml DL load generator if test -z "$OCAMLDLGEN"; then AC_CHECK_PROGS(OCAMLDLGEN, ocamldlgen) fi - AC_MSG_CHECKING(for Ocaml package tool) - if test -z "$OCAMLFIND"; then + # OCaml package tool + if test -z "$OCAMLFIND"; then AC_CHECK_PROGS(OCAMLFIND, ocamlfind) fi - AC_MSG_CHECKING(for Ocaml compiler) - if test -z "$OCAMLC"; then - AC_CHECK_PROGS(OCAMLC, ocamlc) - fi - - AC_MSG_CHECKING(for Ocaml toplevel creator) + # OCaml toplevel creator if test -z "$OCAMLMKTOP"; then AC_CHECK_PROGS(OCAMLMKTOP, ocamlmktop) fi - - AC_MSG_CHECKING(for Ocaml Pre-Processor-Pretty-Printer) - if test -z "$CAMLP4"; then - AC_CHECK_PROGS(CAMLP4, camlp4) - fi -fi # Disabling ocaml +fi AC_SUBST(OCAMLC) +AC_SUBST(CAMLP4) AC_SUBST(OCAMLDLGEN) AC_SUBST(OCAMLFIND) AC_SUBST(OCAMLMKTOP) -AC_SUBST(CAMLP4) - -#---------------------------------------------------------------- -# Look for Pike -#---------------------------------------------------------------- - -# Identify the name of the Pike executable -# Priority: configure option, automatic search -PIKEBIN= -AC_ARG_WITH(pike, AS_HELP_STRING([--without-pike], [Disable Pike]) -AS_HELP_STRING([--with-pike=path], [Set location of Pike executable]),[PIKEBIN="$withval"], [PIKEBIN="$alllang_default"]) - -# First, check for "--without-pike" or "--with-pike=no". -if test x"${PIKEBIN}" = xno; then - AC_MSG_NOTICE([Disabling Pike]) - PIKEBIN= -else - -if test "x$PIKEBIN" = xyes; then - AC_CHECK_PROGS(PIKE, pike pike7.8 pike7.6 pike7.4 pike7.2) -else - PIKE="$PIKEBIN" -fi - - -# Check for pike-config -# Priority: configure option, guessed from $PIKE, search from list -AC_ARG_WITH(pike-config, AS_HELP_STRING([--with-pike-config=path], - [Set location of pike-config script]), - [PIKECONFIG="$withval"], [PIKECONFIG=""]) - -if test -z "$PIKECONFIG" -a -n "$PIKE"; then - AC_CHECK_PROGS(PIKECONFIG, $PIKE-config pike-config \ - pike7.6-config pike7.4-config pike7.2-config) -fi - -# Check for a --with-pikeincl option to configure -# Priority: configure option, info from $PIKECONFIG, guessed by pike script -AC_ARG_WITH(pikeincl, AS_HELP_STRING([--with-pikeincl=path], - [Set location of Pike include directory]), - [PIKEINCLUDE="-I$withval"], [PIKEINCLUDE=]) - -if test -n "$PIKE"; then - AC_MSG_CHECKING([for Pike header files]) - if test -z "$PIKEINCLUDE" -a -n "$PIKECONFIG"; then - PIKEINCLUDE=`$PIKECONFIG --cflags` - fi - if test -z "$PIKEINCLUDE" -a -n "$PIKE"; then - PIKEINCLUDE=`$PIKE -x cflags` - if test -z "$PIKEINCLUDE"; then - PIKEPATH=`which $PIKE` - PIKEINCLUDE=`$PIKE Tools/check-include-path.pike $PIKEPATH` - PIKEINCLUDE="-I$PIKEINCLUDE" - fi - fi - - if test -z "$PIKEINCLUDE"; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT($PIKEINCLUDE) - fi -fi -fi - -AC_SUBST(PIKEINCLUDE) -AC_SUBST(PIKECCDLFLAGS) dnl XXX: where is this used/defined? -AC_SUBST(PIKEDYNAMICLINKING) dnl XXX: where is this used/defined? - -#---------------------------------------------------------------- -# Look for CHICKEN -#---------------------------------------------------------------- - -CHICKEN= -CHICKEN_CONFIG= -CHICKENHOME= -CHICKENOPTS= -CHICKENLIB= - - -AC_ARG_WITH(chicken, AS_HELP_STRING([--without-chicken], [Disable CHICKEN]) -AS_HELP_STRING([--with-chicken=path], [Set location of CHICKEN executable]),[ CHICKENBIN="$withval"], [CHICKENBIN="$alllang_default"]) - -# First, check for "--without-chicken" or "--with-chicken=no". -if test x"${CHICKENBIN}" = xno; then -AC_MSG_NOTICE([Disabling CHICKEN]) -else - -if test "x$CHICKENBIN" = xyes; then -AC_CHECK_PROGS(CHICKEN, chicken) -else -CHICKEN="$CHICKENBIN" -fi - -AC_ARG_WITH(chickencsc,[ --with-chickencsc=path Set location of csc executable],[ CHICKEN_CSC="$withval"], [CHICKEN_CSC=]) - -if test -z "$CHICKEN_CSC"; then - AC_CHECK_PROGS(CHICKEN_CSC, csc) - # Both the Microsoft C# compiler and chicken have an executable called csc, so check that this csc is really the chicken one - if test -n "$CHICKEN_CSC" ; then - AC_MSG_CHECKING(whether csc is the chicken compiler) - $CHICKEN_CSC -version 2>/dev/null | grep "chicken" > /dev/null || CHICKEN_CSC="" - if test -z "$CHICKEN_CSC"; then - AC_MSG_RESULT(no) - else - AC_MSG_RESULT(yes) - fi - fi -fi - -AC_ARG_WITH(chickencsi,[ --with-chickencsi=path Set location of csi executable],[ CHICKEN_CSI="$withval"], [CHICKEN_CSI=]) - -if test -z "$CHICKEN_CSI"; then -AC_CHECK_PROGS(CHICKEN_CSI, csi) -fi - -if test -n "$CHICKEN_CSC" ; then - - AC_ARG_WITH(chickenopts,[ --with-chickenopts=args Set compiler options for static CHICKEN generated code],[ - CHICKENOPTS="$withval"], [CHICKENOPTS=]) - AC_ARG_WITH(chickensharedlib,[ --with-chickensharedlib=args Set linker options for shared CHICKEN generated code],[ - CHICKENSHAREDLIB="$withval"], [CHICKENSHAREDLIB=]) - AC_ARG_WITH(chickenlib,[ --with-chickenlib=args Set linker options for static CHICKEN generated code],[ - CHICKENLIB="$withval"], [CHICKENLIB=]) - - AC_MSG_CHECKING(for compiler options for static CHICKEN generated code) - if test -z "$CHICKENOPTS"; then - CHICKENOPTS="`$CHICKEN_CSC -cflags`" - else - CHICKENOPTS="`$CHICKEN_CSC -cflags` $CHICKENOPTS" - fi - if test -z "$CHICKENOPTS"; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT($CHICKENOPTS) - fi - - AC_MSG_CHECKING(for linker options for shared CHICKEN generated code) - if test -z "$CHICKENSHAREDLIB"; then - CHICKENSHAREDLIB="`$CHICKEN_CSC -shared -libs`" - else - CHICKENSHAREDLIB="`$CHICKEN_CSC -shared -libs` $CHICKENSHAREDLIB" - fi - if test -z "$CHICKENSHAREDLIB"; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT($CHICKENSHAREDLIB) - fi - - AC_MSG_CHECKING(for linker options for static CHICKEN generated code) - if test -z "$CHICKENLIB"; then - CHICKENLIB="`$CHICKEN_CSC -libs`" - else - CHICKENLIB="`$CHICKEN_CSC -libs` $CHICKENLIB" - fi - if test -z "$CHICKENLIB"; then - AC_MSG_RESULT(not found) - else - AC_MSG_RESULT($CHICKENLIB) - fi - -fi # have CHICKEN_CONFIG -fi # Check for --without-chicken - -AC_SUBST(CHICKEN) -AC_SUBST(CHICKEN_CSC) -AC_SUBST(CHICKEN_CSI) -AC_SUBST(CHICKENOPTS) -AC_SUBST(CHICKENLIB) -AC_SUBST(CHICKENSHAREDLIB) #---------------------------------------------------------------- # Look for C# @@ -2176,14 +2106,14 @@ else if test -z "$CSHARPCOMPILERBIN" ; then case $host in *-*-cygwin* | *-*-mingw*) - # prefer Mono gmcs (.NET 2.0) over mcs (.NET 1.1) - note mcs-1.2.3 has major pinvoke bug - AC_CHECK_PROGS(CSHARPCOMPILER, csc mono-csc gmcs mcs cscc) + # prefer unified Mono mcs compiler (not to be confused with the ancient .NET 1 mcs) over older/alternative names. + AC_CHECK_PROGS(CSHARPCOMPILER, csc mcs mono-csc gmcs cscc) if test -n "$CSHARPCOMPILER" && test "$CSHARPCOMPILER" = "csc" ; then AC_MSG_CHECKING(whether csc is the Microsoft CSharp compiler) csc 2>/dev/null | grep "C#" > /dev/null || CSHARPCOMPILER="" if test -z "$CSHARPCOMPILER" ; then AC_MSG_RESULT(no) - AC_CHECK_PROGS(CSHARPCOMPILER, mono-csc gmcs mcs cscc) + AC_CHECK_PROGS(CSHARPCOMPILER, mcs mono-csc gmcs cscc) else AC_MSG_RESULT(yes) fi @@ -2301,35 +2231,36 @@ else if test "x$LUABIN" = xyes; then # We look for a versioned Lua binary first, as there can be # multiple versions of Lua installed on some systems (like Debian). - # The search order should match the include-file and library search - # orders below (a Lua shared library built for one version may not - # work with a Lua binary of a different version). AC_PATH_PROGS(LUABIN, [lua5.4 lua5.3 lua5.2 lua5.1 lua]) fi # check version: we need Lua 5.x if test "$LUABIN"; then AC_MSG_CHECKING(Lua version) - # if version 5.x - LUAV5=`$LUABIN -e 'if string.sub(_VERSION,5,5)=="5" then print "1" end'` - # if not version 5.0 - LUAV51=`$LUABIN -e 'if string.sub(_VERSION,5,7)~="5.0" then print "1" end'` - - if test -z "$LUAV5"; then - AC_MSG_WARN(Not Lua 5.x, SWIG does not support this version of Lua) - LUABIN="" - elif test -z "$LUAV51"; then - AC_MSG_RESULT(Lua 5.0.x) + [LUA_VERSION=`$LUABIN -e 'print(string.match(_VERSION, "%d+[.]%d+"))'`] + # For 5.0 and 5.1 header and libraries may be named using 50 or 51. + LUA_VERSION_NO_DOTS= + if test -n "$LUA_VERSION" ; then + AC_MSG_RESULT([Lua $LUA_VERSION.x]) else - AC_MSG_RESULT(Lua 5.1 or later) + AC_MSG_RESULT([failed]) fi + case $LUA_VERSION in + 5.0) LUA_VERSION_NO_DOTS=50 ;; + 5.1) LUA_VERSION_NO_DOTS=51 ;; + 5.*) ;; + *) + AC_MSG_WARN([Not Lua 5.x, SWIG does not support this version of Lua]) + LUABIN="" + ;; + esac fi if test "$LUABIN"; then AC_MSG_CHECKING(whether Lua dynamic loading is enabled) # using Lua to check Lua # lua 5.0 & 5.1 have different fn names - if test -z "$LUAV51"; then + if test "$LUA_VERSION" = "5.0"; then LUADYNAMICLOADLIB=`$LUABIN -e '_,_,c=loadlib("no_such_lib","") if c~="absent" then print "1" end'` else LUADYNAMICLOADLIB=`$LUABIN -e '_,_,c=package.loadlib("no_such_lib","") if c~="absent" then print "1" end'` @@ -2358,7 +2289,12 @@ if test "$LUABIN"; then # The ordering of the include directories to search should match # the ordering of libraries to search in the library test below. inc=/usr/include - dirs="$inc/lua5.4 $inc/lua5.3 $inc/lua5.2 $inc/lua5.1 $inc/lua51 $inc/lua5.0 $inc/lua50 /usr/local/include" + incloc=/usr/local/include + dirs="$inc/lua$LUA_VERSION" + test -z "$LUA_VERSION_NO_DOTS" || dirs="$dirs $inc/lua$LUA_VERSION_NO_DOTS" + dirs="$dirs $incloc/lua$LUA_VERSION" + test -z "$LUA_VERSION_NO_DOTS" || dirs="$dirs $incloc/lua$LUA_VERSION_NO_DOTS" + dirs="$dirs $incloc" for i in $dirs; do #echo "$i" if test -r $i/lua.h; then @@ -2381,11 +2317,13 @@ if test "$LUABIN"; then if test -n "$LUALIB"; then AC_CHECK_FILE($LUALIB/liblua.a,[LUALINK="-L$LUALIB -llua"],[LUABIN=]) else - AC_SEARCH_LIBS(lua_close, [lua lua5.4 lua5.3 lua5.2 lua5.1 lua51 lua5.0 lua50], [LUALINK="-l$ac_lib"],[LUABIN=]) + libs="lua lua$LUA_VERSION" + test -z "$LUA_VERSION_NO_DOTS" || libs="$libs lua$LUA_VERSION_NO_DOTS" + AC_SEARCH_LIBS(lua_close, [$libs], [LUALINK="-l$ac_lib"],[LUABIN=]) fi # adding lualib for lua 5.0 - if test -z "$LUAV51"; then # extra for lua 5.0 + if test "$LUA_VERSION" = "5.0"; then LUALINK="$LUALINK -llualib" fi @@ -2399,52 +2337,6 @@ AC_SUBST(LUAFLAGS) AC_SUBST(LUALINK) AC_SUBST(LUABIN) -#---------------------------------------------------------------- -# Look for Allegro Common Lisp -#---------------------------------------------------------------- - -ALLEGROCLBIN= - -AC_ARG_WITH(allegrocl, AS_HELP_STRING([--without-allegrocl], [Disable Allegro CL]) -AS_HELP_STRING([--with-allegrocl=path], [Set location of Allegro CL executable (alisp)]),[ ALLEGROCLBIN="$withval"], [ALLEGROCLBIN="$alllang_default"]) - -# First, check for "--without-allegrocl" or "--with-allegrocl=no". -if test x"${ALLEGROCLBIN}" = xno; then -AC_MSG_NOTICE([Disabling Allegro CL]) -ALLEGROCLBIN= -else - -# can we find allegrocl? -if test "x$ALLEGROCLBIN" = xyes; then - AC_PATH_PROG(ALLEGROCLBIN, alisp) -fi -fi - -AC_SUBST(ALLEGROCLBIN) - -#---------------------------------------------------------------- -# Look for GNU CLISP -#---------------------------------------------------------------- - -CLISPBIN= - -AC_ARG_WITH(clisp, AS_HELP_STRING([--without-clisp], [Disable CLISP]) -AS_HELP_STRING([--with-clisp=path], [Set location of CLISP executable (clisp)]),[ CLISPBIN="$withval"], [CLISPBIN="$alllang_default"]) - -# First, check for "--without-clisp" or "--with-clisp=no". -if test x"${CLISPBIN}" = xno; then -AC_MSG_NOTICE([Disabling CLISP]) -CLISPBIN= -else - -# can we find clisp? -if test "x$CLISPBIN" = xyes; then - AC_PATH_PROG(CLISPBIN, clisp) -fi -fi - -AC_SUBST(CLISPBIN) - #---------------------------------------------------------------- # Look for GNU R #---------------------------------------------------------------- @@ -2529,7 +2421,7 @@ else GOVERSIONOPTION=version go_version=$($GO $GOVERSIONOPTION | sed -e 's/go version //') case "$go_version" in - go1 | go1.[[01234]]*) + go1 | go1.[[01234]] | go1.[[01234]].*) GOC=$(sh -c "$(go env) && echo \$GOCHAR")c ;; *) @@ -2538,7 +2430,7 @@ else esac AC_MSG_CHECKING([whether go version is too old]) case $go_version in - go1.1* | go1.0* | go1 ) + go1.1.* | go1.1 | go1.0 | go1.0.* | go1 ) AC_MSG_RESULT([yes - minimum version is 1.2]) GO= GOOPT="-intgosize 32" @@ -2556,13 +2448,13 @@ else ;; esac case $go_version in - go1.0* | go1 | go1.1*) + go1.0 | go1.0.* | go1 | go1.1 | go1.1.*) GOOPT="$GOOPT -use-shlib" ;; - go1.2*) + go1.2 | go1.2.*) GO12=true ;; - go1.3* | go1.4*) + go1.3 | go1.3.* | go1.4 | go1.4.*) GO13=true ;; *) @@ -2642,7 +2534,7 @@ void main() { _ACEOF rm -f conftest.$ac_objext AS_IF( - [_AC_DO_STDERR($D1COMPILER conftest.$ac_ext) && test ! -s conftest.err && test -s conftest.$ac_objext], + [$D1COMPILER conftest.$ac_ext 2>&AS_MESSAGE_LOG_FD && test ! -s conftest.err && test -s conftest.$ac_objext], [AC_MSG_RESULT([yes])], [_AC_MSG_LOG_CONFTEST AC_MSG_RESULT([no]) D1COMPILER=] @@ -2665,7 +2557,7 @@ void main() { _ACEOF rm -f conftest.$ac_objext AS_IF( - [_AC_DO_STDERR($D2COMPILER conftest.$ac_ext) && test ! -s conftest.err && test -s conftest.$ac_objext], + [$D2COMPILER conftest.$ac_ext 2>&AS_MESSAGE_LOG_FD && test ! -s conftest.err && test -s conftest.$ac_objext], [AC_MSG_RESULT([yes])], [_AC_MSG_LOG_CONFTEST AC_MSG_RESULT([no]) D2COMPILER=] @@ -2775,26 +2667,12 @@ AC_SUBST(SKIP_PHP) SKIP_OCAML= -if test -z "$OCAMLC" ; then +if test -z "$OCAMLC" || test -z "$CAMLP4" ; then SKIP_OCAML="1" fi AC_SUBST(SKIP_OCAML) -SKIP_PIKE= -if test -z "$PIKE" || test -z "$PIKEINCLUDE" ; then - SKIP_PIKE="1" -fi -AC_SUBST(SKIP_PIKE) - - -SKIP_CHICKEN= -if test -z "$CHICKEN_CSC" || test -z "$CHICKEN"; then - SKIP_CHICKEN="1" -fi -AC_SUBST(SKIP_CHICKEN) - - SKIP_CSHARP= if test -z "$CSHARPCOMPILER" ; then SKIP_CSHARP="1" @@ -2805,9 +2683,6 @@ else fi AC_SUBST(SKIP_CSHARP) -SKIP_MODULA3="1" # Always skipped! -AC_SUBST(SKIP_MODULA3) - SKIP_LUA= # we need LUABIN & dynamic loading if test -z "$LUABIN" || test -z "$LUADYNAMICLOADLIB"; then @@ -2815,36 +2690,12 @@ if test -z "$LUABIN" || test -z "$LUADYNAMICLOADLIB"; then fi AC_SUBST(SKIP_LUA) -SKIP_ALLEGROCL= -if test -z "$ALLEGROCLBIN" ; then - SKIP_ALLEGROCL="1" -fi -AC_SUBST(SKIP_ALLEGROCL) - -SKIP_CLISP= -if test -z "$CLISPBIN" ; then - SKIP_CLISP="1" -fi -AC_SUBST(SKIP_CLISP) - SKIP_R= if test -z "$RBIN" ; then SKIP_R="1" fi AC_SUBST(SKIP_R) -SKIP_CFFI= -#if test -z "$CFFIBIN" ; then - SKIP_CFFI="1" -#fi -AC_SUBST(SKIP_CFFI) - -SKIP_UFFI= -#if test -z "$UFFIBIN" ; then - SKIP_UFFI="1" -#fi -AC_SUBST(SKIP_UFFI) - SKIP_C= if test -x "$CC" || test -z "$CXX" ; then SKIP_C="1" @@ -2872,16 +2723,6 @@ AC_SUBST(SKIP_D) #---------------------------------------------------------------- # Additional language dependencies #---------------------------------------------------------------- -SKIP_GCJ= -if test -z "$GCJ" || test -z "$GCJH" ; then - SKIP_GCJ="1" -else - if test "$GCC" != yes; then - SKIP_GCJ="1" - fi -fi -AC_SUBST(SKIP_GCJ) - SKIP_ANDROID= if test -z "$ANDROID" || test -z "$ADB" || test -z "$ANT" || test -z "$NDKBUILD" ; then @@ -2968,7 +2809,6 @@ AC_CONFIG_FILES([ Examples/d/example.mk Examples/xml/Makefile Examples/test-suite/errors/Makefile - Examples/test-suite/chicken/Makefile Examples/test-suite/csharp/Makefile Examples/test-suite/d/Makefile Examples/test-suite/guile/Makefile @@ -2979,16 +2819,11 @@ AC_CONFIG_FILES([ Examples/test-suite/octave/Makefile Examples/test-suite/perl5/Makefile Examples/test-suite/php/Makefile - Examples/test-suite/pike/Makefile Examples/test-suite/python/Makefile Examples/test-suite/ruby/Makefile Examples/test-suite/scilab/Makefile Examples/test-suite/tcl/Makefile Examples/test-suite/lua/Makefile - Examples/test-suite/allegrocl/Makefile - Examples/test-suite/clisp/Makefile - Examples/test-suite/cffi/Makefile - Examples/test-suite/uffi/Makefile Examples/test-suite/r/Makefile Examples/test-suite/c/Makefile Examples/test-suite/go/Makefile @@ -3037,10 +2872,6 @@ EOF AC_OUTPUT langs="" -test -n "$SKIP_ALLEGROCL" || langs="${langs}allegrocl " -test -n "$SKIP_CFFI" || langs="${langs}cffi " -test -n "$SKIP_CHICKEN" || langs="${langs}chicken " -test -n "$SKIP_CLISP" || langs="${langs}clisp " test -n "$SKIP_CSHARP" || langs="${langs}csharp " test -n "$SKIP_D" || langs="${langs}d " test -n "$SKIP_GO" || langs="${langs}go " @@ -3048,19 +2879,16 @@ test -n "$SKIP_GUILE" || langs="${langs}guile " test -n "$SKIP_JAVA" || langs="${langs}java " test -n "$SKIP_JAVASCRIPT" || langs="${langs}javascript " test -n "$SKIP_LUA" || langs="${langs}lua " -test -n "$SKIP_MODULA3" || langs="${langs}modula3 " test -n "$SKIP_MZSCHEME" || langs="${langs}mzscheme " test -n "$SKIP_OCAML" || langs="${langs}ocaml " test -n "$SKIP_OCTAVE" || langs="${langs}octave " test -n "$SKIP_PERL5" || langs="${langs}perl5 " test -n "$SKIP_PHP" || langs="${langs}php " -test -n "$SKIP_PIKE" || langs="${langs}pike " test -n "$SKIP_PYTHON" || langs="${langs}python " test -n "$SKIP_R" || langs="${langs}r " test -n "$SKIP_RUBY" || langs="${langs}ruby " test -n "$SKIP_SCILAB" || langs="${langs}scilab " test -n "$SKIP_TCL" || langs="${langs}tcl " -test -n "$SKIP_UFFI" || langs="${langs}uffi " echo " The SWIG test-suite and examples are configured for the following languages: diff --git a/swig.spec.in b/swig.spec.in index 9229274c2..140b96206 100644 --- a/swig.spec.in +++ b/swig.spec.in @@ -27,10 +27,10 @@ with a variety of high-level programming languages. SWIG is primarily used with common scripting languages such as Perl, Python, Tcl/Tk, and Ruby, however the list of supported languages also includes non-scripting languages such as Java, OCAML and C#. Also several interpreted and compiled Scheme implementations -(Guile, MzScheme, Chicken) are supported. SWIG is most commonly used to create +(Guile, MzScheme) are supported. SWIG is most commonly used to create high-level interpreted or compiled programming environments, user interfaces, and as a tool for testing and prototyping C/C++ software. SWIG can also export -its parse tree in the form of XML and Lisp s-expressions. +its parse tree in the form of XML. %prep %setup -q -n %{name}-%{version} diff --git a/vms/aaareadme.txt b/vms/aaareadme.txt deleted file mode 100644 index 52746a7e7..000000000 --- a/vms/aaareadme.txt +++ /dev/null @@ -1,18 +0,0 @@ -Port on OpenVMS 7.3 using CC 6.5 and CXX 6.5 - - -Building procedure: -$ @logicals -$ @build_all - -the logicals swig_root is defined by the procedure logicals.com. -The logicals.com procedure can be invoke with an optional argument -for the define command, for example: -$ @logicals "/system/exec" - - -genbuild.py is the python program use to generate all the procedures in the -[vms.scripts] directory. - - -jf.pieronne@laposte.net diff --git a/vms/build_end.com b/vms/build_end.com deleted file mode 100644 index 103302270..000000000 --- a/vms/build_end.com +++ /dev/null @@ -1,21 +0,0 @@ -$ set def swig_root:[vms] -$ -$ file = f$search("swig_root:[vms.o_alpha]*.obj") -$ newobj = 0 -$ if file .nes. "" -$ then -$ v = f$verify(1) -$ library/replace swig_root:[vms.o_alpha]swig.olb swig_root:[vms.o_alpha]*.obj -$ delete swig_root:[vms.o_alpha]*.obj;* -$ v = f$verify(v) -$ newobj = 1 -$ endif -$ file = f$search("swig_root:[vms]swig.exe") -$ if file .eqs. "" .or. newobj -$ then -$ v = f$verify(1) -$ cxxlink/exe=swig_root:[vms]swig.exe - - /repo=swig_root:[source.modules1_1.cxx_repository] - - swig_root:[vms.o_alpha]swig.olb/include=swigmain -$ v = f$verify(v) -$ endif diff --git a/vms/build_init.com b/vms/build_init.com deleted file mode 100644 index 9a1992dc4..000000000 --- a/vms/build_init.com +++ /dev/null @@ -1,13 +0,0 @@ -$ set def swig_root:[vms] -$ -$ swiglib = "swig_root:[vms.o_alpha]swig.olb -$ -$ if (f$search("swig_root:[vms]o_alpha.dir") .eqs. "") then $ - - create/dir swig_root:[vms.o_alpha] -$ -$ copy swigconfig.h [-.source.include] -$ copy swigver.h [-.source.include] -$ -$ if (f$search("''swiglib'") .eqs. "") then $ - - library/create/object 'swiglib' -$ diff --git a/vms/build_swig.com b/vms/build_swig.com deleted file mode 100644 index 5570db0bc..000000000 --- a/vms/build_swig.com +++ /dev/null @@ -1 +0,0 @@ -$ @swig_root:[vms.scripts]build_all diff --git a/vms/genbuild.py b/vms/genbuild.py deleted file mode 100644 index df18ce3ed..000000000 --- a/vms/genbuild.py +++ /dev/null @@ -1,155 +0,0 @@ -import os.path, string, posix, pyvms -# -# - -IDIR = ['swig_root:[source.swig]', 'swig_root:[source.doh.include]', - 'swig_root:[source.include]', 'swig_root:[source.preprocessor]'] - -def new_file(fg, dirname): - global IDIR - fn = 'swig_root:[vms.scripts]compil_' + os.path.basename(dirname) + '.com' - print >> fg, '$ @' + fn - f = open(fn, 'w') - print >> f, '$!' - print >> f, '$! Generated by genbuild.py' - print >> f, '$!' - print >> f, '$ libname = "swig_root:[vms.o_alpha]swig.olb"' - print >> f, '$' - print >> f, '$ set default', pyvms.crtl_to_vms(dirname)[0][0] - print >> f, '$' - print >> f, "$ idir := ", IDIR[0] - for i in range(1, len(IDIR)): - print >> f, '$ idir = idir + ",' + IDIR[i] + '"' - print >> f, '$' - print >> f, "$ iflags = \"/include=(''idir', sys$disk:[])\"" - print >> f, '$ oflags = \"/object=swig_root:[vms.o_alpha]' - print >> f, "$ cflags = \"''oflags'''iflags'''dflags'\"" - print >> f, "$ cxxflags = \"''oflags'''iflags'''dflags'\"" - print >> f, '$' - return f - - -def end_file(f): - print >>f,"""$ exit -$! -$! -$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES -$ V = 'F$Verify(0) -$! P1 = What we are trying to make -$! P2 = Command to make it -$! P3 = Source file -$! P4 - P8 What it depends on -$ -$ modname = f$parse(p3,,,"name") -$ set noon -$ set message/nofacility/noident/noseverity/notext -$ libr/lis=swig_root:[vms]swiglib.tmp/full/width=132/only='modname' 'libname' -$ set message/facility/ident/severity/text -$ on error then exit -$ open/read swigtmp swig_root:[vms]swiglib.tmp -$! skip header -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$! -$ -$ read/end=module_not_found swigtmp r -$ modfound = 1 -$ Time = f$cvtime(f$extract(49, 20, r)) -$ goto end_search_module -$ module_not_found: -$ modfound = 0 -$ -$ end_search_module: -$ close swigtmp -$ delete swig_root:[vms]swiglib.tmp;* -$ -$ if modfound .eq. 0 then $ goto Makeit -$ -$! Time = F$CvTime(F$File(P1,"RDT")) -$arg=3 -$Loop: -$ Argument = P'arg -$ If Argument .Eqs. "" Then Goto Exit -$ El=0 -$Loop2: -$ File = F$Element(El," ",Argument) -$ If File .Eqs. " " Then Goto Endl -$ AFile = "" -$Loop3: -$ OFile = AFile -$ AFile = F$Search(File) -$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl -$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit -$ Goto Loop3 -$NextEL: -$ El = El + 1 -$ Goto Loop2 -$EndL: -$ arg=arg+1 -$ If arg .Le. 8 Then Goto Loop -$ Goto Exit -$ -$Makeit: -$ VV=F$VERIFY(1) -$ 'P2' 'P3' -$ VV='F$Verify(VV) -$Exit: -$ If V Then Set Verify -$ENDSUBROUTINE""" - - -def listRep(args, dirname, filenames): - fg = args[0] - first = 1 - for fn in filenames: - if fn[-2:] == '.c': - if first: - first = 0 - fc = new_file(fg, dirname) - - cstr = "\"cc ''cflags'\" " - line = "$ call make swig_root:[vms.o_alpha]" - line += fn[:-1] + 'obj -' - print >> fc, line - line = "\t" + cstr + fn - print >> fc, line - elif fn[-4:] == '.cxx': - if first: - first = 0 - fc = new_file(fg, dirname) - - cstr = "\"cxx ''cxxflags'\" " - line = "$ call make swig_root:[vms.o_alpha]" - line += fn[:-3] + 'obj -' - print >> fc, line - line = "\t" + cstr + fn - print >> fc, line - if first == 0: - end_file(fc) - fc.close() -# -def genbuild(f, dir): - os.path.walk(dir, listRep, (f,)) - cmd = 'set default swig_root:[vms]' -# -f = open('swig_root:[vms.scripts]build_all.com','w') -print >> f, '$!' -print >> f, '$! Generated by genbuild.py' -print >> f, '$!' -print >> f, '$ set default swig_root:[vms]' -print >> f, '$' -print >> f, '$ @swig_root:[vms]build_init' -# -genbuild(f, '/swig_root/source') -print >> f, '$' -print >> f, '$ set default swig_root:[vms]' -print >> f, '$' -print >> f, '$ @swig_root:[vms]build_end' -f.close diff --git a/vms/logicals.com b/vms/logicals.com deleted file mode 100644 index 20da9d49a..000000000 --- a/vms/logicals.com +++ /dev/null @@ -1,18 +0,0 @@ -$! -$! -$! -$ proc = f$environment("PROCEDURE") -$ proc = f$parse(proc,"sys$disk:[]",,,"NO_CONCEAL") -$ cur_dev = f$parse(proc,,,"DEVICE","SYNTAX_ONLY") -$ cur_dir = f$parse(proc,,,"DIRECTORY","SYNTAX_ONLY") -$ cur_dir = f$extract(1,f$length(cur_dir)-2,cur_dir) -$ cur_dir = cur_dir - "[" -$ cur_dir = cur_dir - "]" -$ cur_dir = cur_dir - "<" -$ cur_dir = cur_dir - ">" -$ -$! remove trealing .VMS -$ root_dir = f$extract(0,f$length(cur_dir)-4,cur_dir) -$ -$ define 'p1' /trans=concealed swig_root 'cur_dev'['root_dir'.] - diff --git a/vms/scripts/build_all.com b/vms/scripts/build_all.com deleted file mode 100644 index d41198348..000000000 --- a/vms/scripts/build_all.com +++ /dev/null @@ -1,15 +0,0 @@ -$! -$! Generated by genbuild.py -$! -$ set default swig_root:[vms] -$ -$ @swig_root:[vms]build_init -$ @swig_root:[vms.scripts]compil_cparse.com -$ @swig_root:[vms.scripts]compil_doh.com -$ @swig_root:[vms.scripts]compil_modules1_1.com -$ @swig_root:[vms.scripts]compil_preprocessor.com -$ @swig_root:[vms.scripts]compil_swig.com -$ -$ set default swig_root:[vms] -$ -$ @swig_root:[vms]build_end diff --git a/vms/scripts/compil_cparse.com b/vms/scripts/compil_cparse.com deleted file mode 100644 index 4f78f4104..000000000 --- a/vms/scripts/compil_cparse.com +++ /dev/null @@ -1,98 +0,0 @@ -$! -$! Generated by genbuild.py -$! -$ libname = "swig_root:[vms.o_alpha]swig.olb" -$ -$ set default SWIG_ROOT:[SOURCE.CPARSE] -$ -$ idir := swig_root:[source.swig] -$ idir = idir + ",swig_root:[source.doh.include]" -$ idir = idir + ",swig_root:[source.include]" -$ idir = idir + ",swig_root:[source.preprocessor]" -$ -$ iflags = "/include=(''idir', sys$disk:[])" -$ oflags = "/object=swig_root:[vms.o_alpha] -$ cflags = "''oflags'''iflags'''dflags'" -$ cxxflags = "''oflags'''iflags'''dflags'" -$ -$ call make swig_root:[vms.o_alpha]cscanner.obj - - "cc ''cflags'" cscanner.c -$ call make swig_root:[vms.o_alpha]parser.obj - - "cc ''cflags'" parser.c -$ call make swig_root:[vms.o_alpha]templ.obj - - "cc ''cflags'" templ.c -$ call make swig_root:[vms.o_alpha]util.obj - - "cc ''cflags'" util.c -$ exit -$! -$! -$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES -$ V = 'F$Verify(0) -$! P1 = What we are trying to make -$! P2 = Command to make it -$! P3 = Source file -$! P4 - P8 What it depends on -$ -$ modname = f$parse(p3,,,"name") -$ set noon -$ set message/nofacility/noident/noseverity/notext -$ libr/lis=swig_root:[vms]swiglib.tmp/full/width=132/only='modname' 'libname' -$ set message/facility/ident/severity/text -$ on error then exit -$ open/read swigtmp swig_root:[vms]swiglib.tmp -$! skip header -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$! -$ -$ read/end=module_not_found swigtmp r -$ modfound = 1 -$ Time = f$cvtime(f$extract(49, 20, r)) -$ goto end_search_module -$ module_not_found: -$ modfound = 0 -$ -$ end_search_module: -$ close swigtmp -$ delete swig_root:[vms]swiglib.tmp;* -$ -$ if modfound .eq. 0 then $ goto Makeit -$ -$! Time = F$CvTime(F$File(P1,"RDT")) -$arg=3 -$Loop: -$ Argument = P'arg -$ If Argument .Eqs. "" Then Goto Exit -$ El=0 -$Loop2: -$ File = F$Element(El," ",Argument) -$ If File .Eqs. " " Then Goto Endl -$ AFile = "" -$Loop3: -$ OFile = AFile -$ AFile = F$Search(File) -$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl -$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit -$ Goto Loop3 -$NextEL: -$ El = El + 1 -$ Goto Loop2 -$EndL: -$ arg=arg+1 -$ If arg .Le. 8 Then Goto Loop -$ Goto Exit -$ -$Makeit: -$ VV=F$VERIFY(1) -$ 'P2' 'P3' -$ VV='F$Verify(VV) -$Exit: -$ If V Then Set Verify -$ENDSUBROUTINE diff --git a/vms/scripts/compil_doh.com b/vms/scripts/compil_doh.com deleted file mode 100644 index 6d4ae89ad..000000000 --- a/vms/scripts/compil_doh.com +++ /dev/null @@ -1,106 +0,0 @@ -$! -$! Generated by genbuild.py -$! -$ libname = "swig_root:[vms.o_alpha]swig.olb" -$ -$ set default SWIG_ROOT:[SOURCE.DOH.DOH] -$ -$ idir := swig_root:[source.swig] -$ idir = idir + ",swig_root:[source.doh.include]" -$ idir = idir + ",swig_root:[source.include]" -$ idir = idir + ",swig_root:[source.preprocessor]" -$ -$ iflags = "/include=(''idir', sys$disk:[])" -$ oflags = "/object=swig_root:[vms.o_alpha] -$ cflags = "''oflags'''iflags'''dflags'" -$ cxxflags = "''oflags'''iflags'''dflags'" -$ -$ call make swig_root:[vms.o_alpha]base.obj - - "cc ''cflags'" base.c -$ call make swig_root:[vms.o_alpha]file.obj - - "cc ''cflags'" file.c -$ call make swig_root:[vms.o_alpha]fio.obj - - "cc ''cflags'" fio.c -$ call make swig_root:[vms.o_alpha]hash.obj - - "cc ''cflags'" hash.c -$ call make swig_root:[vms.o_alpha]list.obj - - "cc ''cflags'" list.c -$ call make swig_root:[vms.o_alpha]memory.obj - - "cc ''cflags'" memory.c -$ call make swig_root:[vms.o_alpha]string.obj - - "cc ''cflags'" string.c -$ call make swig_root:[vms.o_alpha]void.obj - - "cc ''cflags'" void.c -$ exit -$! -$! -$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES -$ V = 'F$Verify(0) -$! P1 = What we are trying to make -$! P2 = Command to make it -$! P3 = Source file -$! P4 - P8 What it depends on -$ -$ modname = f$parse(p3,,,"name") -$ set noon -$ set message/nofacility/noident/noseverity/notext -$ libr/lis=swig_root:[vms]swiglib.tmp/full/width=132/only='modname' 'libname' -$ set message/facility/ident/severity/text -$ on error then exit -$ open/read swigtmp swig_root:[vms]swiglib.tmp -$! skip header -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$! -$ -$ read/end=module_not_found swigtmp r -$ modfound = 1 -$ Time = f$cvtime(f$extract(49, 20, r)) -$ goto end_search_module -$ module_not_found: -$ modfound = 0 -$ -$ end_search_module: -$ close swigtmp -$ delete swig_root:[vms]swiglib.tmp;* -$ -$ if modfound .eq. 0 then $ goto Makeit -$ -$! Time = F$CvTime(F$File(P1,"RDT")) -$arg=3 -$Loop: -$ Argument = P'arg -$ If Argument .Eqs. "" Then Goto Exit -$ El=0 -$Loop2: -$ File = F$Element(El," ",Argument) -$ If File .Eqs. " " Then Goto Endl -$ AFile = "" -$Loop3: -$ OFile = AFile -$ AFile = F$Search(File) -$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl -$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit -$ Goto Loop3 -$NextEL: -$ El = El + 1 -$ Goto Loop2 -$EndL: -$ arg=arg+1 -$ If arg .Le. 8 Then Goto Loop -$ Goto Exit -$ -$Makeit: -$ VV=F$VERIFY(1) -$ 'P2' 'P3' -$ VV='F$Verify(VV) -$Exit: -$ If V Then Set Verify -$ENDSUBROUTINE diff --git a/vms/scripts/compil_modules1_1.com b/vms/scripts/compil_modules1_1.com deleted file mode 100644 index c570dfe58..000000000 --- a/vms/scripts/compil_modules1_1.com +++ /dev/null @@ -1,132 +0,0 @@ -$! -$! Generated by genbuild.py -$! -$ libname = "swig_root:[vms.o_alpha]swig.olb" -$ -$ set default SWIG_ROOT:[SOURCE.MODULES1_1] -$ -$ idir := swig_root:[source.swig] -$ idir = idir + ",swig_root:[source.doh.include]" -$ idir = idir + ",swig_root:[source.include]" -$ idir = idir + ",swig_root:[source.preprocessor]" -$ -$ iflags = "/include=(''idir', sys$disk:[])" -$ oflags = "/object=swig_root:[vms.o_alpha] -$ cflags = "''oflags'''iflags'''dflags'" -$ cxxflags = "''oflags'''iflags'''dflags'" -$ -$ call make swig_root:[vms.o_alpha]allocate.obj - - "cxx ''cxxflags'" allocate.cxx -$ call make swig_root:[vms.o_alpha]browser.obj - - "cxx ''cxxflags'" browser.cxx -$ call make swig_root:[vms.o_alpha]contract.obj - - "cxx ''cxxflags'" contract.cxx -$ call make swig_root:[vms.o_alpha]emit.obj - - "cxx ''cxxflags'" emit.cxx -$ call make swig_root:[vms.o_alpha]guile.obj - - "cxx ''cxxflags'" guile.cxx -$ call make swig_root:[vms.o_alpha]java.obj - - "cxx ''cxxflags'" java.cxx -$ call make swig_root:[vms.o_alpha]lang.obj - - "cxx ''cxxflags'" lang.cxx -$ call make swig_root:[vms.o_alpha]main.obj - - "cxx ''cxxflags'" main.cxx -$ call make swig_root:[vms.o_alpha]module.obj - - "cxx ''cxxflags'" module.cxx -$ call make swig_root:[vms.o_alpha]mzscheme.obj - - "cxx ''cxxflags'" mzscheme.cxx -$ call make swig_root:[vms.o_alpha]ocaml.obj - - "cxx ''cxxflags'" ocaml.cxx -$ call make swig_root:[vms.o_alpha]overload.obj - - "cxx ''cxxflags'" overload.cxx -$ call make swig_root:[vms.o_alpha]perl5.obj - - "cxx ''cxxflags'" perl5.cxx -$ call make swig_root:[vms.o_alpha]php4.obj - - "cxx ''cxxflags'" php4.cxx -$ call make swig_root:[vms.o_alpha]pike.obj - - "cxx ''cxxflags'" pike.cxx -$ call make swig_root:[vms.o_alpha]python.obj - - "cxx ''cxxflags'" python.cxx -$ call make swig_root:[vms.o_alpha]ruby.obj - - "cxx ''cxxflags'" ruby.cxx -$ call make swig_root:[vms.o_alpha]swigmain.obj - - "cxx ''cxxflags'" swigmain.cxx -$ call make swig_root:[vms.o_alpha]tcl8.obj - - "cxx ''cxxflags'" tcl8.cxx -$ call make swig_root:[vms.o_alpha]typepass.obj - - "cxx ''cxxflags'" typepass.cxx -$ call make swig_root:[vms.o_alpha]xml.obj - - "cxx ''cxxflags'" xml.cxx -$ exit -$! -$! -$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES -$ V = 'F$Verify(0) -$! P1 = What we are trying to make -$! P2 = Command to make it -$! P3 = Source file -$! P4 - P8 What it depends on -$ -$ modname = f$parse(p3,,,"name") -$ set noon -$ set message/nofacility/noident/noseverity/notext -$ libr/lis=swig_root:[vms]swiglib.tmp/full/width=132/only='modname' 'libname' -$ set message/facility/ident/severity/text -$ on error then exit -$ open/read swigtmp swig_root:[vms]swiglib.tmp -$! skip header -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$! -$ -$ read/end=module_not_found swigtmp r -$ modfound = 1 -$ Time = f$cvtime(f$extract(49, 20, r)) -$ goto end_search_module -$ module_not_found: -$ modfound = 0 -$ -$ end_search_module: -$ close swigtmp -$ delete swig_root:[vms]swiglib.tmp;* -$ -$ if modfound .eq. 0 then $ goto Makeit -$ -$! Time = F$CvTime(F$File(P1,"RDT")) -$arg=3 -$Loop: -$ Argument = P'arg -$ If Argument .Eqs. "" Then Goto Exit -$ El=0 -$Loop2: -$ File = F$Element(El," ",Argument) -$ If File .Eqs. " " Then Goto Endl -$ AFile = "" -$Loop3: -$ OFile = AFile -$ AFile = F$Search(File) -$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl -$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit -$ Goto Loop3 -$NextEL: -$ El = El + 1 -$ Goto Loop2 -$EndL: -$ arg=arg+1 -$ If arg .Le. 8 Then Goto Loop -$ Goto Exit -$ -$Makeit: -$ VV=F$VERIFY(1) -$ 'P2' 'P3' -$ VV='F$Verify(VV) -$Exit: -$ If V Then Set Verify -$ENDSUBROUTINE diff --git a/vms/scripts/compil_preprocessor.com b/vms/scripts/compil_preprocessor.com deleted file mode 100644 index f95961e8d..000000000 --- a/vms/scripts/compil_preprocessor.com +++ /dev/null @@ -1,94 +0,0 @@ -$! -$! Generated by genbuild.py -$! -$ libname = "swig_root:[vms.o_alpha]swig.olb" -$ -$ set default SWIG_ROOT:[SOURCE.PREPROCESSOR] -$ -$ idir := swig_root:[source.swig] -$ idir = idir + ",swig_root:[source.doh.include]" -$ idir = idir + ",swig_root:[source.include]" -$ idir = idir + ",swig_root:[source.preprocessor]" -$ -$ iflags = "/include=(''idir', sys$disk:[])" -$ oflags = "/object=swig_root:[vms.o_alpha] -$ cflags = "''oflags'''iflags'''dflags'" -$ cxxflags = "''oflags'''iflags'''dflags'" -$ -$ call make swig_root:[vms.o_alpha]cpp.obj - - "cc ''cflags'" cpp.c -$ call make swig_root:[vms.o_alpha]expr.obj - - "cc ''cflags'" expr.c -$ exit -$! -$! -$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES -$ V = 'F$Verify(0) -$! P1 = What we are trying to make -$! P2 = Command to make it -$! P3 = Source file -$! P4 - P8 What it depends on -$ -$ modname = f$parse(p3,,,"name") -$ set noon -$ set message/nofacility/noident/noseverity/notext -$ libr/lis=swig_root:[vms]swiglib.tmp/full/width=132/only='modname' 'libname' -$ set message/facility/ident/severity/text -$ on error then exit -$ open/read swigtmp swig_root:[vms]swiglib.tmp -$! skip header -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$! -$ -$ read/end=module_not_found swigtmp r -$ modfound = 1 -$ Time = f$cvtime(f$extract(49, 20, r)) -$ goto end_search_module -$ module_not_found: -$ modfound = 0 -$ -$ end_search_module: -$ close swigtmp -$ delete swig_root:[vms]swiglib.tmp;* -$ -$ if modfound .eq. 0 then $ goto Makeit -$ -$! Time = F$CvTime(F$File(P1,"RDT")) -$arg=3 -$Loop: -$ Argument = P'arg -$ If Argument .Eqs. "" Then Goto Exit -$ El=0 -$Loop2: -$ File = F$Element(El," ",Argument) -$ If File .Eqs. " " Then Goto Endl -$ AFile = "" -$Loop3: -$ OFile = AFile -$ AFile = F$Search(File) -$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl -$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit -$ Goto Loop3 -$NextEL: -$ El = El + 1 -$ Goto Loop2 -$EndL: -$ arg=arg+1 -$ If arg .Le. 8 Then Goto Loop -$ Goto Exit -$ -$Makeit: -$ VV=F$VERIFY(1) -$ 'P2' 'P3' -$ VV='F$Verify(VV) -$Exit: -$ If V Then Set Verify -$ENDSUBROUTINE diff --git a/vms/scripts/compil_swig.com b/vms/scripts/compil_swig.com deleted file mode 100644 index 103e275f4..000000000 --- a/vms/scripts/compil_swig.com +++ /dev/null @@ -1,122 +0,0 @@ -$! -$! Generated by genbuild.py -$! -$ libname = "swig_root:[vms.o_alpha]swig.olb" -$ -$ set default SWIG_ROOT:[SOURCE.SWIG] -$ -$ idir := swig_root:[source.swig] -$ idir = idir + ",swig_root:[source.doh.include]" -$ idir = idir + ",swig_root:[source.include]" -$ idir = idir + ",swig_root:[source.preprocessor]" -$ -$ iflags = "/include=(''idir', sys$disk:[])" -$ oflags = "/object=swig_root:[vms.o_alpha] -$ cflags = "''oflags'''iflags'''dflags'" -$ cxxflags = "''oflags'''iflags'''dflags'" -$ -$ call make swig_root:[vms.o_alpha]cwrap.obj - - "cc ''cflags'" cwrap.c -$ call make swig_root:[vms.o_alpha]error.obj - - "cc ''cflags'" error.c -$ call make swig_root:[vms.o_alpha]fragment.obj - - "cc ''cflags'" fragment.c -$ call make swig_root:[vms.o_alpha]getopt.obj - - "cc ''cflags'" getopt.c -$ call make swig_root:[vms.o_alpha]include.obj - - "cc ''cflags'" include.c -$ call make swig_root:[vms.o_alpha]misc.obj - - "cc ''cflags'" misc.c -$ call make swig_root:[vms.o_alpha]naming.obj - - "cc ''cflags'" naming.c -$ call make swig_root:[vms.o_alpha]parms.obj - - "cc ''cflags'" parms.c -$ call make swig_root:[vms.o_alpha]scanner.obj - - "cc ''cflags'" scanner.c -$ call make swig_root:[vms.o_alpha]stype.obj - - "cc ''cflags'" stype.c -$ call make swig_root:[vms.o_alpha]symbol.obj - - "cc ''cflags'" symbol.c -$ call make swig_root:[vms.o_alpha]tree.obj - - "cc ''cflags'" tree.c -$ call make swig_root:[vms.o_alpha]typemap.obj - - "cc ''cflags'" typemap.c -$ call make swig_root:[vms.o_alpha]typesys.obj - - "cc ''cflags'" typesys.c -$ call make swig_root:[vms.o_alpha]warn.obj - - "cc ''cflags'" warn.c -$ call make swig_root:[vms.o_alpha]wrapfunc.obj - - "cc ''cflags'" wrapfunc.c -$ exit -$! -$! -$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES -$ V = 'F$Verify(0) -$! P1 = What we are trying to make -$! P2 = Command to make it -$! P3 = Source file -$! P4 - P8 What it depends on -$ -$ modname = f$parse(p3,,,"name") -$ set noon -$ set message/nofacility/noident/noseverity/notext -$ libr/lis=swig_root:[vms]swiglib.tmp/full/width=132/only='modname' 'libname' -$ set message/facility/ident/severity/text -$ on error then exit -$ open/read swigtmp swig_root:[vms]swiglib.tmp -$! skip header -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$ read swigtmp r -$! -$ -$ read/end=module_not_found swigtmp r -$ modfound = 1 -$ Time = f$cvtime(f$extract(49, 20, r)) -$ goto end_search_module -$ module_not_found: -$ modfound = 0 -$ -$ end_search_module: -$ close swigtmp -$ delete swig_root:[vms]swiglib.tmp;* -$ -$ if modfound .eq. 0 then $ goto Makeit -$ -$! Time = F$CvTime(F$File(P1,"RDT")) -$arg=3 -$Loop: -$ Argument = P'arg -$ If Argument .Eqs. "" Then Goto Exit -$ El=0 -$Loop2: -$ File = F$Element(El," ",Argument) -$ If File .Eqs. " " Then Goto Endl -$ AFile = "" -$Loop3: -$ OFile = AFile -$ AFile = F$Search(File) -$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl -$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit -$ Goto Loop3 -$NextEL: -$ El = El + 1 -$ Goto Loop2 -$EndL: -$ arg=arg+1 -$ If arg .Le. 8 Then Goto Loop -$ Goto Exit -$ -$Makeit: -$ VV=F$VERIFY(1) -$ 'P2' 'P3' -$ VV='F$Verify(VV) -$Exit: -$ If V Then Set Verify -$ENDSUBROUTINE diff --git a/vms/swigconfig.h b/vms/swigconfig.h deleted file mode 100644 index 3ee086407..000000000 --- a/vms/swigconfig.h +++ /dev/null @@ -1,2 +0,0 @@ - -/* Note that this file has changed. TODO Get the latest from the original version. */