diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 1b8a3f671..165b84bf9 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -43,6 +43,7 @@
  • Further details on the Python class interface @@ -2203,6 +2204,16 @@ of low-level details were omitted. This section provides a brief overview of how the proxy classes work.

    +

    New in SWIG version 2.0.3: +The use of Python proxy classes has performance implications that may be +unacceptable for a high-performance library. The new -builtin +option instructs SWIG to forego the use of proxy classes, and instead +create wrapped types as new built-in Python types. When this option is used, +the following section ("Proxy classes") does not apply. Details on the use of +the -builtin option are in the Built-in Classes +section. +

    +

    33.4.1 Proxy classes

    @@ -2292,8 +2303,280 @@ 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).

    -

    33.4.2 Memory management

    +

    33.4.2 Built-in Classes

    +

    +The -builtin option provides a significant performance improvement +in the wrapped code. To understand the difference between proxy classes +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 +like in a proxy class: +

    + +
    +
    +class Foo(object):
    +     def __init__(self):
    +         self.this = _example.new_Foo()
    +         self.thisown = 1
    +
    +
    + +

    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:

    + + + +

    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:

    + +

    http://docs.python.org/extending/newtypes.html

    + +

    33.4.2.1 Limitations

    + +

    Use of the -builtin option implies a couple of limitations: +

    +

    + +

    +To illustrate the last point, if you have a wrapped class called MyString, +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;
    +    ...
    +};
    +
    +
    + +

    +SWIG will automatically create an operator overload in python that will allow this: +

    + +
    +
    +from MyModule import MyString
    +
    +mystr = MyString("No one expects")
    +episode = mystr + " the Spanish Inquisition"
    +
    +
    + +

    +This works because the first operand (mystr) defines a way +to add a native string to itself. However, the following will not work: +

    + +
    +
    +from MyModule import MyString
    +
    +mystr = MyString("Parrot")
    +episode = "Dead " + mystr
    +
    +
    + +

    +The above code fails, because the first operand -- a native python string -- +doesn't know how to add an instance of MyString to itself. +

    + +

    33.4.2.2 Operator overloads -- 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", +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 +slot entries. For example, suppose you have this class: + +

    +
    +class Twit {
    +public:
    +    Twit operator+ (const Twit& twit) const;
    +
    +    // 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:

    + +
    +
    +from MyModule import Twit
    +
    +nigel = Twit()
    +emily = Twit()
    +percival = nigel + emily
    +percival = nigel.add(emily)
    +
    +
    + +

    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 +slot operators. For a complete list of C++ operators that are +automatically converted to python slot operators, refer to the file +python/pyopers.swig in the SWIG library. +

    + +

    There are other very useful python slots that you +may explicitly define using %feature directives. For example, +suppose you want to use instances of a wrapped class as keys in a native python +dict. That will work as long as you define a hash function for +instances of your class, and use it to define the python tp_hash +slot: +

    + +
    +
    +class Cheese {
    +public:
    +    Cheese (const char *name);
    +    long cheeseHashFunc () const;
    +};
    +
    +%feature("python:slot", "tp_hash", functype="hashfunc") Cheese::cheeseHashFunc;
    +
    +
    + +

    This will allow you to write python code like this:

    + +
    +
    +from my MyPackage import Cheese
    +
    +inventory = {
    +    Cheese("cheddar") : 0,
    +    Cheese("gouda") : 0,
    +    Cheese("camembert") : 0
    +}
    +
    +
    + +

    Because you defined the tp_hash slot, Cheese objects may +be used as hash keys; and when the cheeseHashFunc method is invoked +by a python dict, it will not go through named method dispatch. +A more detailed discussion about %feature("python:slot") can be found +in the file python/pyopers.swig in the SWIG library. +You can read about all of the available python slots here:

    + +

    http://docs.python.org/c-api/typeobj.html

    + +

    You may override (almost) all of the slots defined in the PyTypeObject, +PyNumberMethods, PyMappingMethods, PySequenceMethods, and PyBufferProcs +structs. +

    + + +

    33.4.3 Memory management

    + +

    NOTE: Although this section refers to proxy objects, everything here also applies +when the -builtin option is used.

    Associated with proxy object, is an ownership flag .thisown The value of this @@ -2484,7 +2767,7 @@ It is also possible to deal with situations like this using typemaps--an advanced topic discussed later.

    -

    33.4.3 Python 2.2 and classic classes

    +

    33.4.4 Python 2.2 and classic classes

    diff --git a/Examples/python/performance/Makefile b/Examples/python/performance/Makefile new file mode 100644 index 000000000..c6a1e9e98 --- /dev/null +++ b/Examples/python/performance/Makefile @@ -0,0 +1,35 @@ +ifeq (,$(PY3)) + PYSCRIPT = runme.py +else + PYSCRIPT = runme3.py +endif + +default : all + +include ../../Makefile + +SUBDIRS := constructor func hierarchy operator hierarchy_operator + +all : $(SUBDIRS:%=%-build) + @for subdir in $(SUBDIRS); do \ + echo Running $$subdir test... ; \ + echo -------------------------------------------------------------------------------- ; \ + cd $$subdir; \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PYTHONPATH=$(srcdir):$$PYTHONPATH $(PYTHON) $(PYSCRIPT); \ + cd ..; \ + done + +$(SUBDIRS) : + $(MAKE) -C $@ + @echo Running $$subdir test... + @echo -------------------------------------------------------------------------------- + cd $@ && env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PYTHONPATH=$(srcdir):$$PYTHONPATH $(PYTHON) $(PYSCRIPT) + +%-build : + $(MAKE) -C $* + +%-clean : + $(MAKE) -s -C $* clean + +clean : $(SUBDIRS:%=%-clean) + rm -f *.pyc diff --git a/Examples/python/performance/constructor/Makefile b/Examples/python/performance/constructor/Makefile new file mode 100644 index 000000000..48449875c --- /dev/null +++ b/Examples/python/performance/constructor/Makefile @@ -0,0 +1,21 @@ +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = Simple +INTERFACE = Simple.i + +all : + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -module Simple_baseline' \ + TARGET='$(TARGET)_baseline' INTERFACE='$(INTERFACE)' python_cpp + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -O -module Simple_optimized' \ + TARGET='$(TARGET)_optimized' INTERFACE='$(INTERFACE)' python_cpp + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -builtin -O -module Simple_builtin' \ + TARGET='$(TARGET)_builtin' INTERFACE='$(INTERFACE)' python_cpp + +static : + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mypython' INTERFACE='$(INTERFACE)' python_cpp_static + +clean : + $(MAKE) -f $(TOP)/Makefile python_clean + rm -f $(TARGET).py diff --git a/Examples/python/performance/constructor/Simple.i b/Examples/python/performance/constructor/Simple.i new file mode 100644 index 000000000..d642d15bf --- /dev/null +++ b/Examples/python/performance/constructor/Simple.i @@ -0,0 +1,8 @@ +%inline %{ +class MyClass { +public: + MyClass () {} + ~MyClass () {} + void func () {} +}; +%} diff --git a/Examples/python/performance/constructor/runme.py b/Examples/python/performance/constructor/runme.py new file mode 100644 index 000000000..23577a14d --- /dev/null +++ b/Examples/python/performance/constructor/runme.py @@ -0,0 +1,11 @@ +#!/usr/bin/env + +import sys +sys.path.append('..') +import harness + +def proc (mod) : + for i in range(1000000) : + x = mod.MyClass() + +harness.run(proc) diff --git a/Examples/python/performance/func/Makefile b/Examples/python/performance/func/Makefile new file mode 100644 index 000000000..0df09d908 --- /dev/null +++ b/Examples/python/performance/func/Makefile @@ -0,0 +1,23 @@ +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = Simple +INTERFACE = Simple.i + +default : all + +all : + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -module Simple_baseline' \ + TARGET='$(TARGET)_baseline' INTERFACE='$(INTERFACE)' python_cpp + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -O -module Simple_optimized' \ + TARGET='$(TARGET)_optimized' INTERFACE='$(INTERFACE)' python_cpp + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -builtin -O -module Simple_builtin' \ + TARGET='$(TARGET)_builtin' INTERFACE='$(INTERFACE)' python_cpp + +static : + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mypython' INTERFACE='$(INTERFACE)' python_cpp_static + +clean : + $(MAKE) -f $(TOP)/Makefile python_clean + rm -f $(TARGET).py diff --git a/Examples/python/performance/func/Simple.i b/Examples/python/performance/func/Simple.i new file mode 100644 index 000000000..d642d15bf --- /dev/null +++ b/Examples/python/performance/func/Simple.i @@ -0,0 +1,8 @@ +%inline %{ +class MyClass { +public: + MyClass () {} + ~MyClass () {} + void func () {} +}; +%} diff --git a/Examples/python/performance/func/runme.py b/Examples/python/performance/func/runme.py new file mode 100644 index 000000000..fd2fb175b --- /dev/null +++ b/Examples/python/performance/func/runme.py @@ -0,0 +1,12 @@ +#!/usr/bin/env + +import sys +sys.path.append('..') +import harness + +def proc (mod) : + x = mod.MyClass() + for i in range(10000000) : + x.func() + +harness.run(proc) diff --git a/Examples/python/performance/harness.py b/Examples/python/performance/harness.py new file mode 100644 index 000000000..8e9b6041b --- /dev/null +++ b/Examples/python/performance/harness.py @@ -0,0 +1,30 @@ +#!/usr/bin/env + +import sys +import time +import imp +from subprocess import * + +def run (proc) : + + try : + mod = imp.find_module(sys.argv[1]) + mod = imp.load_module(sys.argv[1], *mod) + + t1 = time.clock() + proc(mod) + t2 = time.clock() + print "%s took %f seconds" % (mod.__name__, t2 - t1) + + except IndexError : + proc = Popen([sys.executable, 'runme.py', 'Simple_baseline'], stdout=PIPE) + (stdout, stderr) = proc.communicate() + print stdout + + proc = Popen([sys.executable, 'runme.py', 'Simple_optimized'], stdout=PIPE) + (stdout, stderr) = proc.communicate() + print stdout + + proc = Popen([sys.executable, 'runme.py', 'Simple_builtin'], stdout=PIPE) + (stdout, stderr) = proc.communicate() + print stdout diff --git a/Examples/python/performance/hierarchy/Makefile b/Examples/python/performance/hierarchy/Makefile new file mode 100644 index 000000000..0df09d908 --- /dev/null +++ b/Examples/python/performance/hierarchy/Makefile @@ -0,0 +1,23 @@ +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = Simple +INTERFACE = Simple.i + +default : all + +all : + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -module Simple_baseline' \ + TARGET='$(TARGET)_baseline' INTERFACE='$(INTERFACE)' python_cpp + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -O -module Simple_optimized' \ + TARGET='$(TARGET)_optimized' INTERFACE='$(INTERFACE)' python_cpp + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -builtin -O -module Simple_builtin' \ + TARGET='$(TARGET)_builtin' INTERFACE='$(INTERFACE)' python_cpp + +static : + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mypython' INTERFACE='$(INTERFACE)' python_cpp_static + +clean : + $(MAKE) -f $(TOP)/Makefile python_clean + rm -f $(TARGET).py diff --git a/Examples/python/performance/hierarchy/Simple.i b/Examples/python/performance/hierarchy/Simple.i new file mode 100644 index 000000000..b4f43ec3e --- /dev/null +++ b/Examples/python/performance/hierarchy/Simple.i @@ -0,0 +1,52 @@ +%inline %{ + +class A { +public: + A () {} + ~A () {} + void func () {} +}; + +class B : public A { +public: + B () {} + ~B () {} +}; + +class C : public B { +public: + C () {} + ~C () {} +}; + +class D : public C { +public: + D () {} + ~D () {} +}; + +class E : public D { +public: + E () {} + ~E () {} +}; + +class F : public E { +public: + F () {} + ~F () {} +}; + +class G : public F { +public: + G () {} + ~G () {} +}; + +class H : public G { +public: + H () {} + ~H () {} +}; + +%} diff --git a/Examples/python/performance/hierarchy/runme.py b/Examples/python/performance/hierarchy/runme.py new file mode 100644 index 000000000..8a57da05e --- /dev/null +++ b/Examples/python/performance/hierarchy/runme.py @@ -0,0 +1,12 @@ +#!/usr/bin/env + +import sys +sys.path.append('..') +import harness + +def proc (mod) : + x = mod.H() + for i in range(10000000) : + x.func() + +harness.run(proc) diff --git a/Examples/python/performance/hierarchy_operator/Makefile b/Examples/python/performance/hierarchy_operator/Makefile new file mode 100644 index 000000000..0df09d908 --- /dev/null +++ b/Examples/python/performance/hierarchy_operator/Makefile @@ -0,0 +1,23 @@ +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = Simple +INTERFACE = Simple.i + +default : all + +all : + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -module Simple_baseline' \ + TARGET='$(TARGET)_baseline' INTERFACE='$(INTERFACE)' python_cpp + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -O -module Simple_optimized' \ + TARGET='$(TARGET)_optimized' INTERFACE='$(INTERFACE)' python_cpp + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -builtin -O -module Simple_builtin' \ + TARGET='$(TARGET)_builtin' INTERFACE='$(INTERFACE)' python_cpp + +static : + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mypython' INTERFACE='$(INTERFACE)' python_cpp_static + +clean : + $(MAKE) -f $(TOP)/Makefile python_clean + rm -f $(TARGET).py diff --git a/Examples/python/performance/hierarchy_operator/Simple.i b/Examples/python/performance/hierarchy_operator/Simple.i new file mode 100644 index 000000000..b26bcf31d --- /dev/null +++ b/Examples/python/performance/hierarchy_operator/Simple.i @@ -0,0 +1,53 @@ +%inline %{ + +class A { +public: + A () {} + ~A () {} + void func () {} + A& operator+= (int i) { return *this; } +}; + +class B : public A { +public: + B () {} + ~B () {} +}; + +class C : public B { +public: + C () {} + ~C () {} +}; + +class D : public C { +public: + D () {} + ~D () {} +}; + +class E : public D { +public: + E () {} + ~E () {} +}; + +class F : public E { +public: + F () {} + ~F () {} +}; + +class G : public F { +public: + G () {} + ~G () {} +}; + +class H : public G { +public: + H () {} + ~H () {} +}; + +%} diff --git a/Examples/python/performance/hierarchy_operator/runme.py b/Examples/python/performance/hierarchy_operator/runme.py new file mode 100644 index 000000000..cf200362f --- /dev/null +++ b/Examples/python/performance/hierarchy_operator/runme.py @@ -0,0 +1,12 @@ +#!/usr/bin/env + +import sys +sys.path.append('..') +import harness + +def proc (mod) : + x = mod.H() + for i in range(10000000) : + x += i + +harness.run(proc) diff --git a/Examples/python/performance/operator/Makefile b/Examples/python/performance/operator/Makefile new file mode 100644 index 000000000..0df09d908 --- /dev/null +++ b/Examples/python/performance/operator/Makefile @@ -0,0 +1,23 @@ +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = Simple +INTERFACE = Simple.i + +default : all + +all : + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -module Simple_baseline' \ + TARGET='$(TARGET)_baseline' INTERFACE='$(INTERFACE)' python_cpp + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -O -module Simple_optimized' \ + TARGET='$(TARGET)_optimized' INTERFACE='$(INTERFACE)' python_cpp + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG) -builtin -O -module Simple_builtin' \ + TARGET='$(TARGET)_builtin' INTERFACE='$(INTERFACE)' python_cpp + +static : + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mypython' INTERFACE='$(INTERFACE)' python_cpp_static + +clean : + $(MAKE) -f $(TOP)/Makefile python_clean + rm -f $(TARGET).py diff --git a/Examples/python/performance/operator/Simple.i b/Examples/python/performance/operator/Simple.i new file mode 100644 index 000000000..fb0dd992c --- /dev/null +++ b/Examples/python/performance/operator/Simple.i @@ -0,0 +1,8 @@ +%inline %{ +class MyClass { +public: + MyClass () {} + ~MyClass () {} + MyClass& operator+ (int i) { return *this; } +}; +%} diff --git a/Examples/python/performance/operator/runme.py b/Examples/python/performance/operator/runme.py new file mode 100644 index 000000000..61a0e8edc --- /dev/null +++ b/Examples/python/performance/operator/runme.py @@ -0,0 +1,12 @@ +#!/usr/bin/env + +import sys +sys.path.append('..') +import harness + +def proc (mod) : + x = mod.MyClass() + for i in range(10000000) : + x = x + i + +harness.run(proc) diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index a05542b70..3b0769019 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -61,6 +61,7 @@ CPP_TEST_CASES += \ python_kwargs \ python_nondynamic \ python_overload_simple_cast \ + python_richcompare \ std_containers \ swigobject \ template_matrix \ diff --git a/Examples/test-suite/python/argcargvtest_runme.py b/Examples/test-suite/python/argcargvtest_runme.py index 584a19f6e..047ea9551 100644 --- a/Examples/test-suite/python/argcargvtest_runme.py +++ b/Examples/test-suite/python/argcargvtest_runme.py @@ -2,16 +2,16 @@ from argcargvtest import * largs=['hi','hola','hello'] if mainc(largs) != 3: - raise RuntimeError, "bad main typemap" + raise RuntimeError("bad main typemap") targs=('hi','hola') if mainv(targs,1) != 'hola': - print mainv(targs,1) - raise RuntimeError, "bad main typemap" + print(mainv(targs,1)) + raise RuntimeError("bad main typemap") targs=('hi', 'hola') if mainv(targs,1) != 'hola': - raise RuntimeError, "bad main typemap" + raise RuntimeError("bad main typemap") try: error = 0 @@ -20,7 +20,7 @@ try: except TypeError: pass if error: - raise RuntimeError, "bad main typemap" + raise RuntimeError("bad main typemap") diff --git a/Examples/test-suite/python/default_constructor_runme.py b/Examples/test-suite/python/default_constructor_runme.py index 334eaa8af..59b130559 100644 --- a/Examples/test-suite/python/default_constructor_runme.py +++ b/Examples/test-suite/python/default_constructor_runme.py @@ -1,3 +1,7 @@ +# This test is expected to fail with -builtin option. +# It uses the old static syntax (e.g., dc.new_A() rather than dc.A()), +# which is not provided with the -builtin option. + import _default_constructor dc = _default_constructor diff --git a/Examples/test-suite/python/director_exception_runme.py b/Examples/test-suite/python/director_exception_runme.py index 82be1289b..510845a5a 100644 --- a/Examples/test-suite/python/director_exception_runme.py +++ b/Examples/test-suite/python/director_exception_runme.py @@ -66,11 +66,15 @@ except MyException, e: if not ok: raise RuntimeError +# This is expected to fail with -builtin option +# Throwing builtin classes as exceptions not supported try: raise Exception2() except Exception2: pass +# This is expected to fail with -builtin option +# Throwing builtin classes as exceptions not supported try: raise Exception1() except Exception1: diff --git a/Examples/test-suite/python/exception_order_runme.py b/Examples/test-suite/python/exception_order_runme.py index 0b0b1c08d..38b53eb0c 100644 --- a/Examples/test-suite/python/exception_order_runme.py +++ b/Examples/test-suite/python/exception_order_runme.py @@ -1,5 +1,7 @@ from exception_order import * +# This test is expected to fail with -builtin option. +# Throwing builtin classes as exceptions not supported a = A() diff --git a/Examples/test-suite/python/grouping_runme.py b/Examples/test-suite/python/grouping_runme.py index 13f8c8c92..36f9b38de 100644 --- a/Examples/test-suite/python/grouping_runme.py +++ b/Examples/test-suite/python/grouping_runme.py @@ -11,3 +11,4 @@ if x != -37: raise RuntimeError grouping.cvar.test3 = 42 +grouping.test3 = 42 diff --git a/Examples/test-suite/python/li_std_set_runme.py b/Examples/test-suite/python/li_std_set_runme.py index 6d8963138..449333e73 100644 --- a/Examples/test-suite/python/li_std_set_runme.py +++ b/Examples/test-suite/python/li_std_set_runme.py @@ -92,5 +92,5 @@ sum = () for i in s: sum = sum + (i,) -if sum != (1, 'hello', (1, 2)): +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 cef5921b0..9e9e3d2c3 100644 --- a/Examples/test-suite/python/li_std_string_extra_runme.py +++ b/Examples/test-suite/python/li_std_string_extra_runme.py @@ -54,9 +54,13 @@ if a + b != "hello world": if a + " world" != "hello world": raise RuntimeError, "bad string mapping" +# This is expected to fail with -builtin option +# Reverse operators not supported in builtin types if "hello" + b != "hello world": raise RuntimeError, "bad string mapping" +# This is expected to fail with -builtin option +# Reverse operators not supported in builtin types c = "hello" + b if c.find_last_of("l") != 9: 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 a4b9d3ee2..a2d419a0a 100644 --- a/Examples/test-suite/python/li_std_wstring_runme.py +++ b/Examples/test-suite/python/li_std_wstring_runme.py @@ -4,21 +4,21 @@ x=u"h" if li_std_wstring.test_wcvalue(x) != x: print li_std_wstring.test_wcvalue(x) - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") x=u"hello" if li_std_wstring.test_ccvalue(x) != x: - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") if li_std_wstring.test_cvalue(x) != x: - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") if li_std_wstring.test_value(x) != x: print x, li_std_wstring.test_value(x) - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") if li_std_wstring.test_const_reference(x) != x: - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") s = li_std_wstring.wstring(u"he") @@ -26,39 +26,41 @@ s = s + u"llo" if s != x: print s, x - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") if s[1:4] != x[1:4]: - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") if li_std_wstring.test_value(s) != x: - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") if li_std_wstring.test_const_reference(s) != x: - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") a = li_std_wstring.A(s) if li_std_wstring.test_value(a) != x: - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") if li_std_wstring.test_const_reference(a) != x: - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") b = li_std_wstring.wstring(" world") if a + b != "hello world": - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") if a + " world" != "hello world": - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") +# This is expected to fail if -builtin is used if "hello" + b != "hello world": - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") +# This is expected to fail if -builtin is used c = "hello" + b if c.find_last_of("l") != 9: - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") s = "hello world" @@ -66,11 +68,11 @@ b = li_std_wstring.B("hi") b.name = li_std_wstring.wstring(u"hello") if b.name != "hello": - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") b.a = li_std_wstring.A("hello") if b.a != u"hello": - raise RuntimeError, "bad string mapping" + raise RuntimeError("bad string mapping") diff --git a/Examples/test-suite/python/python_abstractbase_runme3.py b/Examples/test-suite/python/python_abstractbase_runme3.py index e34777558..b7593f109 100644 --- a/Examples/test-suite/python/python_abstractbase_runme3.py +++ b/Examples/test-suite/python/python_abstractbase_runme3.py @@ -1,5 +1,9 @@ from python_abstractbase import * from collections import * + +# This is expected to fail with -builtin option +# Builtin types can't inherit from pure-python abstract bases + assert issubclass(Mapii, MutableMapping) assert issubclass(Multimapii, MutableMapping) assert issubclass(IntSet, MutableSet) diff --git a/Examples/test-suite/python/python_nondynamic_runme.py b/Examples/test-suite/python/python_nondynamic_runme.py index 27755db9c..b860ba0d7 100644 --- a/Examples/test-suite/python/python_nondynamic_runme.py +++ b/Examples/test-suite/python/python_nondynamic_runme.py @@ -13,7 +13,6 @@ except: if not err: raise RuntimeError, "A is not static" - class B(python_nondynamic.A): c = 4 def __init__(self): @@ -21,10 +20,19 @@ class B(python_nondynamic.A): pass pass - - bb = B() -bb.c = 3 + +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" + try: bb.d = 2 err = 0 @@ -33,7 +41,6 @@ except: if not err: raise RuntimeError, "B is not static" - cc = python_nondynamic.C() cc.d = 3 diff --git a/Examples/test-suite/python/python_richcompare_runme.py b/Examples/test-suite/python/python_richcompare_runme.py new file mode 100644 index 000000000..e077989cc --- /dev/null +++ b/Examples/test-suite/python/python_richcompare_runme.py @@ -0,0 +1,100 @@ +import python_richcompare + +base1 = python_richcompare.BaseClass(1) +base2 = python_richcompare.BaseClass(2) +base3 = python_richcompare.BaseClass(3) +a1 = python_richcompare.SubClassA(1) +a2 = python_richcompare.SubClassA(2) +a3 = python_richcompare.SubClassA(3) +b1 = python_richcompare.SubClassB(1) +b2 = python_richcompare.SubClassB(2) +b3 = python_richcompare.SubClassB(3) + +# Check == and != within a single type +#------------------------------------------------------------------------------- + +if not (base1 == base1) : + raise RuntimeError("Object not == to itself") + +if not (base1 == python_richcompare.BaseClass(1)) : + raise RuntimeError("Object not == to an equivalent object") + +if (base1 == base2) : + raise RuntimeError("Comparing non-equivalent objects of the same type, == returned True") + +if (base1 != base1) : + raise RuntimeError("Object is != itself") + +if (base1 != python_richcompare.BaseClass(1)) : + raise RuntimeError("Object is != an equivalent object") + +if not (base1 != base2) : + raise RuntimeError("Comparing non-equivalent objects of the same type, != returned False") + + +# Check redefined operator== in SubClassA +#------------------------------------------------------------------------------- + +if (a2 == base2) : + raise RuntimeError("Redefined operator== in SubClassA failed") + +if (a2 == b2) : + raise RuntimeError("Redefined operator== in SubClassA failed") + +if not (a1 == a2) : + raise RuntimeError("Redefined operator== in SubClassA failed") + +# Check up-casting of subclasses +#------------------------------------------------------------------------------- + +if (base2 != a2) : + raise RuntimeError("Comparing equivalent base and subclass instances, != returned True") + +if (a2 == base2) : + raise RuntimeError("Comparing non-equivalent base and subclass instances, == returned True") + +if (a1 == b1) : + raise RuntimeError("Comparing equivalent instances of different subclasses, == returned True") + +if (b1 == a1) : + raise RuntimeError("Comparing equivalent instances of different subclasses, == returned True") + +# Check inequalities +#------------------------------------------------------------------------------- + +if (a2 > b2) : + raise RuntimeError("operator> failed") + +if (a2 < b2) : + raise RuntimeError("operator< failed") + +if not (a2 >= b2) : + raise RuntimeError("operator>= failed") + +if not (a2 <= b2) : + raise RuntimeError("operator<= failed") + +# Check inequalities used for ordering +#------------------------------------------------------------------------------- + +x = sorted([a2, a3, a1]) + +if not (x[0] is a1) : + raise RuntimeError("Ordering failed") + +if not (x[1] is a2) : + raise RuntimeError("Ordering failed") + +if not (x[2] is a3) : + raise RuntimeError("Ordering failed") + +x = sorted([base2, a3, b1]) + +if not (x[0] is b1) : + raise RuntimeError("Ordering failed") + +if not (x[1] is base2) : + raise RuntimeError("Ordering failed") + +if not (x[2] is a3) : + raise RuntimeError("Ordering failed") diff --git a/Examples/test-suite/python/threads_exception_runme.py b/Examples/test-suite/python/threads_exception_runme.py index 9fbc6a9b2..56fe4fd78 100644 --- a/Examples/test-suite/python/threads_exception_runme.py +++ b/Examples/test-suite/python/threads_exception_runme.py @@ -18,8 +18,11 @@ except RuntimeError,e: if e.args[0] != "I died.": raise RuntimeError +# This is expected fail with -builtin option +# Throwing builtin classes as exceptions not supported try: t.hosed() + pass except threads_exception.Exc,e: if e.code != 42: raise RuntimeError diff --git a/Examples/test-suite/python_richcompare.i b/Examples/test-suite/python_richcompare.i new file mode 100644 index 000000000..142d0594b --- /dev/null +++ b/Examples/test-suite/python_richcompare.i @@ -0,0 +1,60 @@ +/* Test the tp_richcompare functions generated with the -builtin option */ + +%module python_richcompare + +%inline { + +class BaseClass { +public: + BaseClass (int i_) : i(i_) {} + ~BaseClass () {} + + int getValue () const + { return i; } + + bool operator< (const BaseClass& x) const + { return this->i < x.i; } + + bool operator> (const BaseClass& x) const + { return this->i > x.i; } + + bool operator<= (const BaseClass& x) const + { return this->i <= x.i; } + + bool operator>= (const BaseClass& x) const + { return this->i >= x.i; } + + bool operator== (const BaseClass& x) const + { return this->i == x.i; } + + bool operator!= (const BaseClass& x) const + { return this->i != x.i; } + + int i; +}; + +class SubClassA : public BaseClass { +public: + SubClassA (int i_) : BaseClass(i_) {} + ~SubClassA () {} + + bool operator== (const SubClassA& x) const + { return true; } + + bool operator== (const BaseClass& x) const + { return false; } +}; + +class SubClassB : public BaseClass { +public: + SubClassB (int i_) : BaseClass(i_) {} + ~SubClassB () {} + + bool operator== (const SubClassB& x) const + { return true; } + + bool operator== (const SubClassA& x) const + { return false; } +}; + +} diff --git a/Lib/python/boost_shared_ptr.i b/Lib/python/boost_shared_ptr.i index e8c536026..bae1576c2 100644 --- a/Lib/python/boost_shared_ptr.i +++ b/Lib/python/boost_shared_ptr.i @@ -6,6 +6,10 @@ #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...) @@ -75,7 +79,8 @@ $1 = %const_cast((smartarg ? smartarg->get() : 0), $1_ltype); } } -%typemap(out, fragment="SWIG_null_deleter") CONST TYPE * { + +%typemap(out, fragment="SWIG_null_deleter_python") 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)); } @@ -98,7 +103,7 @@ $1 = %const_cast((smartarg ? smartarg->get() : 0), $1_ltype); } } -%typemap(varout, fragment="SWIG_null_deleter") CONST TYPE * { +%typemap(varout, fragment="SWIG_null_deleter_python") 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)); } @@ -119,7 +124,7 @@ $1 = %const_cast(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get(), $1_ltype); } } -%typemap(out, fragment="SWIG_null_deleter") CONST TYPE & { +%typemap(out, fragment="SWIG_null_deleter_python") 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)); } @@ -141,7 +146,7 @@ $1 = *%const_cast(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get(), $1_ltype); } } -%typemap(varout, fragment="SWIG_null_deleter") CONST TYPE & { +%typemap(varout, fragment="SWIG_null_deleter_python") 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)); } @@ -163,7 +168,7 @@ } $1 = &temp; } -%typemap(out, fragment="SWIG_null_deleter") TYPE *CONST& { +%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); %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -311,5 +316,16 @@ %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; + + +#if defined(SWIGPYTHON_BUILTIN) + +%typemap(builtin_init, fragment="SWIG_null_deleter_python") 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_Python_NewBuiltinObj(self, %as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), $owner | SWIG_POINTER_OWN)); +} + +#endif + %enddef diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg new file mode 100644 index 000000000..ca9d8ab15 --- /dev/null +++ b/Lib/python/builtin.swg @@ -0,0 +1,421 @@ +#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 = (SwigPyObject *)a; \ + if (sobj->own) { \ + PyObject *o = wrapper(a, NULL); \ + Py_XDECREF(o); \ + } \ +} + +#define SWIGPY_INQUIRY_CLOSURE(wrapper) \ +SWIGINTERN int \ +wrapper##_closure(PyObject *a) { \ + PyObject *pyresult = wrapper(a, NULL); \ + int 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 = PyTuple_New(1); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, b); \ + Py_XINCREF(b); \ + PyObject *result = wrapper(a, tuple); \ + Py_DECREF(tuple); \ + return result; \ +} + +#define SWIGPY_TERNARYFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_closure(PyObject *a, PyObject *b, PyObject *c) { \ + PyObject *tuple = PyTuple_New(2); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, b); \ + PyTuple_SET_ITEM(tuple, 1, c); \ + Py_XINCREF(b); \ + Py_XINCREF(c); \ + PyObject *result = wrapper(a, tuple); \ + Py_DECREF(tuple); \ + return result; \ +} + +#define SWIGPY_LENFUNC_CLOSURE(wrapper) \ +SWIGINTERN Py_ssize_t \ +wrapper##_closure(PyObject *a) { \ + PyObject *resultobj = wrapper(a, NULL); \ + Py_ssize_t 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 = PyTuple_New(2); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ + PyTuple_SET_ITEM(tuple, 1, _PyLong_FromSsize_t(c)); \ + PyObject *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 = 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); \ + } \ + PyObject *resultobj = wrapper(a, tuple); \ + int 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 = PyTuple_New(1); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ + PyObject *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 = _PyLong_FromSsize_t(b); \ + PyObject *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 = PyTuple_New(2); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ + PyTuple_SET_ITEM(tuple, 1, c); \ + Py_XINCREF(c); \ + PyObject *resultobj = wrapper(a, tuple); \ + int 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 = 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); \ + } \ + PyObject *resultobj = wrapper(a, tuple); \ + int 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 long \ +wrapper##_closure(PyObject *a) { \ + PyObject *pyresult = wrapper(a, NULL); \ + if (!pyresult || !PyLong_Check(pyresult)) \ + return -1; \ + long result = PyLong_AsLong(pyresult); \ + Py_DECREF(pyresult); \ + return result; \ +} + +#define SWIGPY_ITERNEXT_CLOSURE(wrapper) \ +SWIGINTERN PyObject * \ +wrapper##_closure(PyObject *a) { \ + PyObject *result = wrapper(a, NULL); \ + if (result && result == Py_None) { \ + Py_DECREF(result); \ + result = NULL; \ + } \ + return result; \ +} + +SWIGINTERN int +SwigPyBuiltin_BadInit(PyObject *self, PyObject *args, PyObject *kwds) { + PyErr_Format(PyExc_TypeError, "Cannot create new instances of type '%.300s'", self->ob_type->tp_name); + return -1; +} + +SWIGINTERN void +SwigPyBuiltin_BadDealloc(PyObject *pyobj) { + SwigPyObject *sobj = (SwigPyObject *)pyobj; + if (sobj->own) { + PyErr_Format(PyExc_TypeError, "Swig detected a memory leak in type '%.300s': no callable destructor found.", pyobj->ob_type->tp_name); + } +} + +typedef struct { + PyCFunction get; + PyCFunction set; +} SwigPyGetSet; + +SWIGINTERN PyObject * +SwigPyBuiltin_GetterClosure (PyObject *obj, void *closure) { + if (!closure) + return SWIG_Py_Void(); + SwigPyGetSet *getset = (SwigPyGetSet *)closure; + if (!getset->get) + return SWIG_Py_Void(); + PyObject *tuple = PyTuple_New(0); + assert(tuple); + PyObject *result = (*getset->get)(obj, tuple); + Py_DECREF(tuple); + return result; +} + +SWIGINTERN PyObject * +SwigPyBuiltin_FunpackGetterClosure (PyObject *obj, void *closure) { + if (!closure) + return SWIG_Py_Void(); + SwigPyGetSet *getset = (SwigPyGetSet *)closure; + if (!getset->get) + return SWIG_Py_Void(); + PyObject *result = (*getset->get)(obj, NULL); + return result; +} + +SWIGINTERN int +SwigPyBuiltin_SetterClosure (PyObject *obj, PyObject *val, void *closure) { + if (!closure) { + PyErr_Format(PyExc_TypeError, "Missing getset closure"); + return -1; + } + SwigPyGetSet *getset = (SwigPyGetSet *)closure; + if (!getset->set) { + PyErr_Format(PyExc_TypeError, "Illegal member variable assignment in type '%.300s'", obj->ob_type->tp_name); + return -1; + } + PyObject *tuple = PyTuple_New(1); + assert(tuple); + PyTuple_SET_ITEM(tuple, 0, val); + Py_XINCREF(val); + PyObject *result = (*getset->set)(obj, tuple); + Py_DECREF(tuple); + Py_XDECREF(result); + return result ? 0 : -1; +} + +SWIGINTERN int +SwigPyBuiltin_FunpackSetterClosure (PyObject *obj, PyObject *val, void *closure) { + if (!closure) { + PyErr_Format(PyExc_TypeError, "Missing getset closure"); + return -1; + } + SwigPyGetSet *getset = (SwigPyGetSet *)closure; + if (!getset->set) { + PyErr_Format(PyExc_TypeError, "Illegal member variable assignment in type '%.300s'", obj->ob_type->tp_name); + return -1; + } + PyObject *result = (*getset->set)(obj, val); + Py_XDECREF(result); + return result ? 0 : -1; +} + +SWIGINTERN void +SwigPyStaticVar_dealloc(PyDescrObject *descr) { + _PyObject_GC_UNTRACK(descr); + Py_XDECREF(descr->d_type); + Py_XDECREF(descr->d_name); + PyObject_GC_Del(descr); +} + +SWIGINTERN PyObject * +SwigPyStaticVar_repr(PyGetSetDescrObject *descr) { +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_FromFormat("", descr->d_name, descr->d_type->tp_name); +#else + return PyString_FromFormat("", PyString_AsString(descr->d_name), descr->d_type->tp_name); +#endif +} + +SWIGINTERN int +SwigPyStaticVar_traverse(PyObject *self, visitproc visit, void *arg) { + PyDescrObject *descr = (PyDescrObject *)self; + Py_VISIT((PyObject*) descr->d_type); + return 0; +} + +SWIGINTERN PyObject * +SwigPyStaticVar_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) { + if (descr->d_getset->get != NULL) + return descr->d_getset->get(obj, descr->d_getset->closure); +#if PY_VERSION_HEX >= 0x03000000 + PyErr_Format(PyExc_AttributeError, "attribute '%.300S' of '%.100s' objects is not readable", descr->d_name, descr->d_type->tp_name); +#else + PyErr_Format(PyExc_AttributeError, "attribute '%.300s' of '%.100s' objects is not readable", PyString_AsString(descr->d_name), descr->d_type->tp_name); +#endif + return NULL; +} + +SWIGINTERN int +SwigPyStaticVar_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) { + int res; + + if (descr->d_getset->set != NULL) + return descr->d_getset->set(obj, value, descr->d_getset->closure); +#if PY_VERSION_HEX >= 0x03000000 + PyErr_Format(PyExc_AttributeError, "attribute '%.300S' of '%.100s' objects is not writable", descr->d_name, descr->d_type->tp_name); +#else + PyErr_Format(PyExc_AttributeError, "attribute '%.300s' of '%.100s' objects is not writable", PyString_AsString(descr->d_name), descr->d_type->tp_name); +#endif + return -1; +} + +SWIGINTERN PyTypeObject SwigPyStaticVar_Type = { +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(&PyType_Type, 0) +#else + PyObject_HEAD_INIT(&PyType_Type) + 0, +#endif + "swig_static_var_getset_descriptor", + sizeof(PyGetSetDescrObject), + 0, + (destructor)SwigPyStaticVar_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)SwigPyStaticVar_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_HAVE_CLASS, /* tp_flags */ + 0, /* tp_doc */ + SwigPyStaticVar_traverse, /* 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 */ + (descrgetfunc)SwigPyStaticVar_get, /* tp_descr_get */ + (descrsetfunc)SwigPyStaticVar_set, /* tp_descr_set */ +}; + +SWIGINTERN int +SwigPyObjectType_setattro(PyTypeObject *type, PyObject *name, PyObject *value) { + PyObject *attribute = _PyType_Lookup(type, name); + if (attribute != NULL) { + /* Implement descriptor functionality, if any */ + descrsetfunc local_set = attribute->ob_type->tp_descr_set; + if (local_set != NULL) + return local_set(attribute, (PyObject *)type, value); +#if PY_VERSION_HEX >= 0x03000000 + PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%.50s.%.400S'", type->tp_name, name); +#else + PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%.50s.%.400s'", type->tp_name, PyString_AS_STRING(name)); +#endif + } else { +#if PY_VERSION_HEX >= 0x03000000 + PyErr_Format(PyExc_AttributeError, "type '%.50s' has no attribute '%.400S'", type->tp_name, name); +#else + PyErr_Format(PyExc_AttributeError, "type '%.50s' has no attribute '%.400s'", type->tp_name, PyString_AS_STRING(name)); +#endif + } + + return -1; +} + +SWIGINTERN PyGetSetDescrObject * +SwigPyStaticVar_new_getset(PyTypeObject *type, PyGetSetDef *getset) { + PyGetSetDescrObject *descr = (PyGetSetDescrObject *)PyType_GenericAlloc(&SwigPyStaticVar_Type, 0); + assert(descr); + Py_XINCREF(type); + descr->d_type = type; + descr->d_name = PyString_InternFromString(getset->name); + descr->d_getset = getset; + if (descr->d_name == NULL) { + Py_DECREF(descr); + descr = NULL; + } + return descr; +} + +SWIGINTERN void +SwigPyBuiltin_InitBases (PyTypeObject *type, PyTypeObject **bases) { + int base_count = 0; + PyTypeObject **b; + int i; + + if (!bases[0]) { + bases[0] = SwigPyObject_type(); + bases[1] = NULL; + } + type->tp_base = bases[0]; + Py_INCREF((PyObject *)bases[0]); + for (b = bases; *b != NULL; ++b) + ++base_count; + PyObject *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]); + } + type->tp_bases = tuple; +} + +SWIGINTERN PyObject * +SwigPyBuiltin_ThisClosure (PyObject *self, void *closure) { + PyObject *result = (PyObject *)SWIG_Python_GetSwigThis(self); + Py_XINCREF(result); + return result; +} + +SWIGINTERN void +SwigPyBuiltin_SetMetaType (PyTypeObject *type, PyTypeObject *metatype) +{ +#if PY_VERSION_HEX >= 0x03000000 + type->ob_base.ob_base.ob_type = metatype; +#else + type->ob_type = metatype; +#endif +} diff --git a/Lib/python/carrays.i b/Lib/python/carrays.i index 8d6d44082..8a881fd0b 100644 --- a/Lib/python/carrays.i +++ b/Lib/python/carrays.i @@ -1,5 +1,49 @@ %define %array_class(TYPE,NAME) +#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 NAME { + 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 %enddef %include diff --git a/Lib/python/director.swg b/Lib/python/director.swg index aa9a10d72..c80695ff7 100644 --- a/Lib/python/director.swg +++ b/Lib/python/director.swg @@ -459,6 +459,18 @@ namespace Swig { } return own; } + + template + static PyObject* swig_pyobj_disown(PyObject *pyobj, PyObject *SWIGUNUSEDPARM(args)) + { + SwigPyObject *sobj = (SwigPyObject *)pyobj; + sobj->own = 0; + Director *d = SWIG_DIRECTOR_CAST(reinterpret_cast(sobj->ptr)); + if (d) + d->swig_disown(); + return PyWeakref_NewProxy(pyobj, NULL); + } + }; #ifdef __THREAD__ diff --git a/Lib/python/pyapi.swg b/Lib/python/pyapi.swg index d980f9263..6d794a67b 100644 --- a/Lib/python/pyapi.swg +++ b/Lib/python/pyapi.swg @@ -32,7 +32,7 @@ typedef struct swig_const_info { * Wrapper of PyInstanceMethod_New() used in Python 3 * It is exported to the generated module, used for -fastproxy * ----------------------------------------------------------------------------- */ -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func) +SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func)) { #if PY_VERSION_HEX >= 0x03000000 return PyInstanceMethod_New(func); diff --git a/Lib/python/pyclasses.swg b/Lib/python/pyclasses.swg index 65f6dec47..b73ebdbb8 100644 --- a/Lib/python/pyclasses.swg +++ b/Lib/python/pyclasses.swg @@ -43,6 +43,9 @@ namespace swig { %apply PyObject * {SwigPtr_PyObject}; %apply PyObject * const& {SwigPtr_PyObject const&}; + %typemap(typecheck,precedence=SWIG_TYPECHECK_SWIGOBJECT,noblock=1) SwigPtr_PyObject const& "$1 = ($input != 0);"; + + /* For output */ %typemap(out,noblock=1) SwigPtr_PyObject { $result = (PyObject *)$1; diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg index 40506e15b..f2e633023 100644 --- a/Lib/python/pycontainer.swg +++ b/Lib/python/pycontainer.swg @@ -245,7 +245,7 @@ namespace swig { template inline void - setslice(Sequence* self, Difference i, Difference j, const InputSeq& v) { + setslice(Sequence* self, Difference i, Difference j, const InputSeq& v = InputSeq()) { typename Sequence::size_type size = self->size(); typename Sequence::size_type ii = swig::check_index(i, size, true); typename Sequence::size_type jj = swig::slice_index(j, size); @@ -586,19 +586,28 @@ namespace swig return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } - %pythoncode {def __iter__(self): return self.iterator()} +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "tp_iter", functype="getiterfunc") iterator; +#else + %pythoncode {def __iter__(self): return self.iterator()} +#endif } + #endif //SWIG_EXPORT_ITERATOR_METHODS %enddef /**** The python container methods ****/ - %define %swig_container_methods(Container...) %newobject __getslice__; +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "nb_nonzero", functype="inquiry") __nonzero__; + %feature("python:slot", "sq_length", functype="lenfunc") __len__; +#endif // SWIGPYTHON_BUILTIN + %extend { bool __nonzero__() const { return !(self->empty()); @@ -613,14 +622,26 @@ namespace swig return self->size(); } } + %enddef + + %define %swig_sequence_methods_common(Sequence...) %swig_sequence_iterator(%arg(Sequence)) %swig_container_methods(%arg(Sequence)) %fragment("SwigPySequence_Base"); +#if defined(SWIGPYTHON_BUILTIN) + //%feature("python:slot", "sq_item", functype="ssizeargfunc") __getitem__; + //%feature("python:slot", "sq_slice", functype="ssizessizeargfunc") __getslice__; + //%feature("python:slot", "sq_ass_item", functype="ssizeobjargproc") __setitem__; + //%feature("python:slot", "sq_ass_slice", functype="ssizessizeobjargproc") __setslice__; + %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__; + %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__; +#endif // SWIGPYTHON_BUILTIN + %extend { value_type pop() throw (std::out_of_range) { if (self->size() == 0) @@ -632,6 +653,9 @@ namespace swig /* typemap for slice object support */ %typemap(in) PySliceObject* { + if (!PySlice_Check($input)) { + %argument_fail(SWIG_TypeError, "$type", $symname, $argnum); + } $1 = (PySliceObject *) $input; } %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) PySliceObject* { @@ -642,7 +666,7 @@ namespace swig return swig::getslice(self, i, j); } - void __setslice__(difference_type i, difference_type j, const Sequence& v) + void __setslice__(difference_type i, difference_type j, const Sequence& v = Sequence()) throw (std::out_of_range, std::invalid_argument) { swig::setslice(self, i, j, v); } @@ -680,6 +704,17 @@ namespace swig swig::setslice(self, i, j, v); } + void __setitem__(PySliceObject *slice) + throw (std::out_of_range) { + Py_ssize_t i, j, step; + if( !PySlice_Check(slice) ) { + SWIG_Error(SWIG_TypeError, "Slice object expected."); + return; + } + PySlice_GetIndices(slice, self->size(), &i, &j, &step); + swig::delslice(self, i,j); + } + void __delitem__(PySliceObject *slice) throw (std::out_of_range) { Py_ssize_t i, j, step; @@ -692,6 +727,7 @@ namespace swig } } + %enddef %define %swig_sequence_methods(Sequence...) @@ -709,6 +745,7 @@ namespace swig self->push_back(x); } } + %enddef %define %swig_sequence_methods_val(Sequence...) @@ -726,6 +763,7 @@ namespace swig self->push_back(x); } } + %enddef diff --git a/Lib/python/pyhead.swg b/Lib/python/pyhead.swg index 2edbf631f..d38b4d91f 100644 --- a/Lib/python/pyhead.swg +++ b/Lib/python/pyhead.swg @@ -5,7 +5,15 @@ #define PyInt_Check(x) PyLong_Check(x) #define PyInt_AsLong(x) PyLong_AsLong(x) #define PyInt_FromLong(x) PyLong_FromLong(x) +#define PyString_Check(name) PyBytes_Check(name) +#define PyString_FromString(x) PyUnicode_FromString(x) #define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) +#define PyString_AsString(str) PyBytes_AsString(str) +#define PyString_Size(str) PyBytes_Size(str) +#define PyString_InternFromString(key) PyUnicode_InternFromString(key) +#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE +#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x) +#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x) #endif @@ -145,4 +153,49 @@ PyObject *PyBool_FromLong(long ok) 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 inline long PyNumber_AsSsize_t (PyObject *x, void*) +{ + long result = 0; + PyObject *i = PyNumber_Int(x); + if (i) { + result = PyInt_AsLong(i); + Py_DECREF(i); + } + return result; +} +#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 diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg index 5af8d2491..088eb0ab0 100644 --- a/Lib/python/pyinit.swg +++ b/Lib/python/pyinit.swg @@ -138,7 +138,7 @@ SWIGINTERN PyTypeObject* swig_varlink_type(void) { static char varlink__doc__[] = "Swig var link object"; static PyTypeObject varlink_type; - static int type_init = 0; + static int type_init = 0; if (!type_init) { const PyTypeObject tmp = { @@ -152,7 +152,7 @@ swig_varlink_type(void) { (char *)"swigvarlink", /* Type name (tp_name) */ sizeof(swig_varlinkobject), /* Basic size (tp_basicsize) */ 0, /* Itemsize (tp_itemsize) */ - (destructor) swig_varlink_dealloc, /* Deallocator (tp_dealloc) */ + (destructor) swig_varlink_dealloc, /* Deallocator (tp_dealloc) */ (printfunc) swig_varlink_print, /* Print (tp_print) */ (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */ (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */ @@ -179,6 +179,9 @@ swig_varlink_type(void) { #if PY_VERSION_HEX >= 0x02030000 0, /* tp_del */ #endif +#if PY_VERSION_HEX >= 0x02060000 + 0, /* tp_version */ +#endif #ifdef COUNT_ALLOCS 0,0,0,0 /* tp_alloc -> tp_next */ #endif @@ -239,7 +242,7 @@ SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { for (i = 0; constants[i].type; ++i) { switch(constants[i].type) { case SWIG_PY_POINTER: - obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); + obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); break; case SWIG_PY_BINARY: obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); @@ -320,7 +323,7 @@ SWIGEXPORT void #endif SWIG_init(void) { - PyObject *m, *d; + PyObject *m, *d, *md; #if PY_VERSION_HEX >= 0x03000000 static struct PyModuleDef SWIG_module = { PyModuleDef_HEAD_INIT, @@ -335,6 +338,25 @@ SWIG_init(void) { }; #endif +#if defined(SWIGPYTHON_BUILTIN) + PyTypeObject *builtin_pytype = 0; + int builtin_base_count = 0; + swig_type_info *builtin_basetype = 0; + PyObject *tuple = NULL; + PyGetSetDescrObject *static_getset = NULL; + + int i; + + /* metatype is used to implement static member variables. */ + PyObject *metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type); + assert(metatype_args); + PyTypeObject *metatype = (PyTypeObject *) PyType_Type.tp_call((PyObject *) &PyType_Type, metatype_args, NULL); + assert(metatype); + Py_DECREF(metatype_args); + metatype->tp_setattro = (setattrofunc) &SwigPyObjectType_setattro; + assert(PyType_Ready(metatype) >= 0); +#endif + /* Fix SwigMethods to carry the callback ptrs when needed */ SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); @@ -343,10 +365,53 @@ SWIG_init(void) { #else m = Py_InitModule((char *) SWIG_name, SwigMethods); #endif - d = PyModule_GetDict(m); - + md = d = PyModule_GetDict(m); + SWIG_InitializeModule(0); + +#ifdef SWIGPYTHON_BUILTIN + static SwigPyClientData SwigPyObject_clientdata = {0}; + SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject"); + assert(SwigPyObject_stype); + SwigPyClientData *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) { + PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules."); +# if PY_VERSION_HEX >= 0x03000000 + return NULL; +# else + return; +# endif + } + + /* All objects have a 'this' attribute */ + static PyGetSetDef this_getset_def = { + (char*) "this", SwigPyBuiltin_ThisClosure, NULL, NULL, NULL + }; + PyObject *this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def); + + /* All objects have a 'thisown' attribute */ + static SwigPyGetSet thisown_getset_closure = { + (PyCFunction) SwigPyObject_own, + (PyCFunction) SwigPyObject_own + }; + static PyGetSetDef thisown_getset_def = { + const_cast("thisown"), SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure + }; + PyObject *thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def); + + PyObject *public_interface = PyList_New(0); + PyObject *public_symbol = 0; + PyDict_SetItemString(md, "__all__", public_interface); + Py_DECREF(public_interface); + for (i = 0; SwigMethods[i].ml_name != NULL; ++i) + SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name); + for (i = 0; swig_const_table[i].name != 0; ++i) + SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name); +#endif + SWIG_InstallConstants(d,swig_const_table); - %} diff --git a/Lib/python/pyiterators.swg b/Lib/python/pyiterators.swg index 3c39f9710..5521027a7 100644 --- a/Lib/python/pyiterators.swg +++ b/Lib/python/pyiterators.swg @@ -128,6 +128,13 @@ namespace swig { return desc; } }; + + inline PyObject* make_output_iterator_builtin (PyObject *pyself) + { + Py_INCREF(pyself); + return pyself; + } + } } @@ -302,6 +309,18 @@ namespace swig { { return new SwigPyIteratorOpen_T(current, seq); } + + template + inline PyObject* make_output_iterator_builtin_T (PyObject *pyself) + { + SwigPyObject *builtin_obj = (SwigPyObject*) pyself; + Sequence *seq = reinterpret_cast< Sequence * >(builtin_obj->ptr); + if (!seq) + return SWIG_Py_Void(); + SwigPyIterator *iter = make_output_iterator(seq->begin(), seq->begin(), seq->end(), pyself); + return SWIG_InternalNewPointerObj(iter, SWIGTYPE_p_swig__SwigPyIterator, SWIG_POINTER_OWN); + } + } } @@ -329,9 +348,15 @@ namespace swig %newobject SwigPyIterator::operator - (ptrdiff_t n) const; %nodirector SwigPyIterator; + +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:tp_iter") SwigPyIterator "&swig::make_output_iterator_builtin"; + %feature("python:slot", "tp_iternext", functype="iternextfunc") SwigPyIterator::__next__; +#else %extend SwigPyIterator { %pythoncode {def __iter__(self): return self} } +#endif %catches(swig::stop_iteration) SwigPyIterator::value() const; %catches(swig::stop_iteration) SwigPyIterator::incr(size_t n = 1); @@ -347,7 +372,6 @@ namespace swig %catches(swig::stop_iteration) SwigPyIterator::operator + (ptrdiff_t n) const; %catches(swig::stop_iteration) SwigPyIterator::operator - (ptrdiff_t n) const; - struct SwigPyIterator { protected: diff --git a/Lib/python/pyopers.swg b/Lib/python/pyopers.swg index 30775b84e..4d7a575dd 100644 --- a/Lib/python/pyopers.swg +++ b/Lib/python/pyopers.swg @@ -1,45 +1,140 @@ /* ------------------------------------------------------------ * Overloaded operator support + + The directives in this file apply whether or not you use the + -builtin option to SWIG, but operator overloads are particularly + attractive when using -builtin, because they are much faster + than named methods. + + If you're using the -builtin option to SWIG, and you want to define + python operator overloads beyond the defaults defined in this file, + here's what you need to know: + + 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. + + To dispatch to a statically defined function, use %feature("python:"), + where is the name of a field in a PyTypeObject, PyNumberMethods, + PyMappingMethods, PySequenceMethods, or PyBufferProcs. For example: + + %{ + + static long myHashFunc (PyObject *pyobj) { + MyClass *cobj; + // Convert pyobj to cobj + return (cobj->field1 * (cobj->field2 << 7)); + } + + %} + + %feature("python:tp_hash") MyClass "myHashFunc"; + + NOTE: It is the responsibility of the programmer (that's you) to ensure + that a statically defined slot function has the correct signature. + + If, instead, you want to dispatch to an instance method, you can + use %feature("python:slot"). For example: + + class MyClass { + public: + long myHashFunc () const; + ... + }; + + %feature("python:slot", "tp_hash", functype="hashfunc") MyClass::myHashFunc; + + 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-marshall + the arguments before dispatching to the wrapped method. Setting + the "functype" attribute of the feature enables SWIG to generate + a correct closure function. + + -------------------------------------------------------------- + + The tp_richcompare slot is a special case: SWIG automatically generates + a rich compare function for all wrapped types. If a type defines C++ + operator overloads for comparison (operator==, operator<, etc.), they + will be called from the generated rich compare function. If you + want to explicitly choose a method to handle a certain comparison + operation, you may use %feature("python:slot") like this: + + class MyClass { + public: + bool lessThan (const MyClass& x) const; + ... + }; + + %feature("python:slot", "Py_LT") MyClass::lessThan; + + ... where "Py_LT" is one of rich comparison opcodes defined in the + python header file object.h. + + If there's no method defined to handle a particular comparsion operation, + the default behavior is to compare pointer values of the wrapped + C++ objects. + + -------------------------------------------------------------- + + + For more information about python slots, including their names and + signatures, you may refer to the python documentation : + + http://docs.python.org/c-api/typeobj.html + * ------------------------------------------------------------ */ #ifdef __cplusplus -#define %pybinoperator(pyname,oper) %rename(pyname) oper; %pythonmaybecall oper - -%pybinoperator(__add__, *::operator+); -%pybinoperator(__pos__, *::operator+()); -%pybinoperator(__pos__, *::operator+() const); -%pybinoperator(__sub__, *::operator-); -%pybinoperator(__neg__, *::operator-()); -%pybinoperator(__neg__, *::operator-() const); -%pybinoperator(__mul__, *::operator*); -%pybinoperator(__div__, *::operator/); -%pybinoperator(__mod__, *::operator%); -%pybinoperator(__lshift__, *::operator<<); -%pybinoperator(__rshift__, *::operator>>); -%pybinoperator(__and__, *::operator&); -%pybinoperator(__or__, *::operator|); -%pybinoperator(__xor__, *::operator^); -%pybinoperator(__lt__, *::operator<); -%pybinoperator(__le__, *::operator<=); -%pybinoperator(__gt__, *::operator>); -%pybinoperator(__ge__, *::operator>=); -%pybinoperator(__eq__, *::operator==); -%pybinoperator(__ne__, *::operator!=); +#if defined(SWIGPYTHON_BUILTIN) +#define %pybinoperator(pyname,oper,functp,slt) %rename(pyname) oper; %pythonmaybecall oper; %feature("python:slot", #slt, functype=#functp) oper; %feature("python:slot", #slt, functype=#functp) pyname; +#define %pycompare(pyname,oper,comptype) %rename(pyname) oper; %pythonmaybecall oper; %feature("python:compare", #comptype) oper; %feature("python:compare", #comptype) pyname; +#else +#define %pybinoperator(pyname,oper,functp,slt) %rename(pyname) oper; %pythonmaybecall oper +#define %pycompare(pyname,oper,comptype) %pybinoperator(pyname,oper,,comptype) +#endif +%pybinoperator(__add__, *::operator+, binaryfunc, nb_add); +%pybinoperator(__pos__, *::operator+(), unaryfunc, nb_positive); +%pybinoperator(__pos__, *::operator+() const, unaryfunc, nb_positive); +%pybinoperator(__sub__, *::operator-, binaryfunc, nb_subtract); +%pybinoperator(__neg__, *::operator-(), unaryfunc, nb_negative); +%pybinoperator(__neg__, *::operator-() const, unaryfunc, nb_negative); +%pybinoperator(__mul__, *::operator*, binaryfunc, nb_multiply); +%pybinoperator(__div__, *::operator/, binaryfunc, nb_div); +%pybinoperator(__mod__, *::operator%, binaryfunc, nb_remainder); +%pybinoperator(__lshift__, *::operator<<, binaryfunc, nb_lshift); +%pybinoperator(__rshift__, *::operator>>, binaryfunc, nb_rshift); +%pybinoperator(__and__, *::operator&, binaryfunc, nb_and); +%pybinoperator(__or__, *::operator|, binaryfunc, nb_or); +%pybinoperator(__xor__, *::operator^, binaryfunc, nb_xor); +%pycompare(__lt__, *::operator<, Py_LT); +%pycompare(__le__, *::operator<=, Py_LE); +%pycompare(__gt__, *::operator>, Py_GT); +%pycompare(__ge__, *::operator>=, Py_GE); +%pycompare(__eq__, *::operator==, Py_EQ); +%pycompare(__ne__, *::operator!=, Py_NE); +%feature("python:slot", "nb_truediv", functype="binaryfunc") *::operator/; /* Special cases */ %rename(__invert__) *::operator~; +%feature("python:slot", "nb_invert", functype="unaryfunc") *::operator~; %rename(__call__) *::operator(); +%feature("python:slot", "tp_call", functype="ternaryfunc") *::operator(); +#if defined(SWIGPYTHON_BUILTIN) +%pybinoperator(__nonzero__, *::operator bool, inquiry, nb_nonzero); +#else %feature("shadow") *::operator bool %{ def __nonzero__(self): return $action(self) __bool__ = __nonzero__ %}; %rename(__nonzero__) *::operator bool; +#endif /* Ignored operators */ %ignoreoperator(LNOT) operator!; @@ -90,18 +185,22 @@ __bool__ = __nonzero__ */ -#define %pyinplaceoper(SwigPyOper, Oper) %delobject Oper; %newobject Oper; %rename(SwigPyOper) Oper +#if defined(SWIGPYTHON_BUILTIN) +#define %pyinplaceoper(SwigPyOper, Oper, functp, slt) %delobject Oper; %newobject Oper; %feature("python:slot", #slt, functype=#functp) Oper; %rename(SwigPyOper) Oper +#else +#define %pyinplaceoper(SwigPyOper, Oper, functp, slt) %delobject Oper; %newobject Oper; %rename(SwigPyOper) Oper +#endif -%pyinplaceoper(__iadd__ , *::operator +=); -%pyinplaceoper(__isub__ , *::operator -=); -%pyinplaceoper(__imul__ , *::operator *=); -%pyinplaceoper(__idiv__ , *::operator /=); -%pyinplaceoper(__imod__ , *::operator %=); -%pyinplaceoper(__iand__ , *::operator &=); -%pyinplaceoper(__ior__ , *::operator |=); -%pyinplaceoper(__ixor__ , *::operator ^=); -%pyinplaceoper(__ilshift__, *::operator <<=); -%pyinplaceoper(__irshift__, *::operator >>=); +%pyinplaceoper(__iadd__ , *::operator +=, binaryfunc, nb_inplace_add); +%pyinplaceoper(__isub__ , *::operator -=, binaryfunc, nb_inplace_subtract); +%pyinplaceoper(__imul__ , *::operator *=, binaryfunc, nb_inplace_multiply); +%pyinplaceoper(__idiv__ , *::operator /=, binaryfunc, nb_inplace_divide); +%pyinplaceoper(__imod__ , *::operator %=, binaryfunc, nb_inplace_remainder); +%pyinplaceoper(__iand__ , *::operator &=, binaryfunc, nb_inplace_and); +%pyinplaceoper(__ior__ , *::operator |=, binaryfunc, nb_inplace_or); +%pyinplaceoper(__ixor__ , *::operator ^=, binaryfunc, nb_inplace_xor); +%pyinplaceoper(__ilshift__, *::operator <<=, binaryfunc, nb_inplace_lshift); +%pyinplaceoper(__irshift__, *::operator >>=, binaryfunc, nb_inplace_rshift); /* Finally, in python we need to mark the binary operations to fail as diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 5043e6ec0..d6e273df1 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -13,7 +13,15 @@ #define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) #define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) #define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags) + +#ifdef SWIGPYTHON_BUILTIN +#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(self, ptr, type, flags) +#else +#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) +#endif + +#define SWIG_InternalNewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) + #define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) #define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) #define swig_owntype int @@ -28,7 +36,7 @@ /* for C or C++ function pointers */ #define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) -#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(ptr, type, 0) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(NULL, ptr, type, 0) /* for C++ member pointers, ie, member methods */ #define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) @@ -71,12 +79,33 @@ SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { /* Set a constant value */ +#if defined(SWIGPYTHON_BUILTIN) + +SWIGINTERN void +SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) { + PyObject *s = PyString_InternFromString(key); + PyList_Append(seq, s); + Py_DECREF(s); +} + +SWIGINTERN void +SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) { + PyDict_SetItemString(d, (char *)name, obj); + Py_DECREF(obj); + if (public_interface) + SwigPyBuiltin_AddPublicSymbol(public_interface, name); +} + +#else + SWIGINTERN void SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { - PyDict_SetItemString(d, (char*) name, obj); + PyDict_SetItemString(d, (char *)name, obj); Py_DECREF(obj); } +#endif + /* Append a value to the result obj */ SWIGINTERN PyObject* @@ -137,6 +166,14 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi } } if (!PyTuple_Check(args)) { + if (min <= 1 && max >= 1) { + objs[0] = args; + register int i; + for (i = 1; i < max; ++i) { + objs[i] = 0; + } + return 2; + } PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); return 0; } else { @@ -189,6 +226,9 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi #define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) +#define SWIG_BUILTIN_TP_INIT (SWIG_POINTER_OWN << 2) +#define SWIG_BUILTIN_INIT (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN) + #ifdef __cplusplus extern "C" { #if 0 @@ -244,6 +284,7 @@ typedef struct { PyObject *destroy; int delargs; int implicitconv; + PyTypeObject *pytype; } SwigPyClientData; SWIGRUNTIMEINLINE int @@ -310,13 +351,13 @@ SwigPyClientData_New(PyObject* obj) data->delargs = 0; } data->implicitconv = 0; + data->pytype = 0; return data; } } SWIGRUNTIME void -SwigPyClientData_Del(SwigPyClientData* data) -{ +SwigPyClientData_Del(SwigPyClientData *data) { Py_XDECREF(data->newraw); Py_XDECREF(data->newargs); Py_XDECREF(data->destroy); @@ -330,6 +371,9 @@ typedef struct { swig_type_info *ty; int own; PyObject *next; +#ifdef SWIGPYTHON_BUILTIN + PyObject *dict; +#endif } SwigPyObject; SWIGRUNTIME PyObject * @@ -380,21 +424,21 @@ SwigPyObject_repr(SwigPyObject *v, PyObject *args) #endif { const char *name = SWIG_TypePrettyName(v->ty); - PyObject *repr = SWIG_Python_str_FromFormat("", name, v); + PyObject *repr = SWIG_Python_str_FromFormat("", name, (void *)v); if (v->next) { -#ifdef METH_NOARGS +# ifdef METH_NOARGS PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); -#else +# else PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); -#endif -#if PY_VERSION_HEX >= 0x03000000 +# endif +# if PY_VERSION_HEX >= 0x03000000 PyObject *joined = PyUnicode_Concat(repr, nrep); Py_DecRef(repr); Py_DecRef(nrep); repr = joined; -#else +# else PyString_ConcatAndDel(&repr,nrep); -#endif +# endif } return repr; } @@ -453,18 +497,38 @@ SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) } -SWIGRUNTIME PyTypeObject* _PySwigObject_type(void); +SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void); +#ifdef SWIGPYTHON_BUILTIN +static swig_type_info *SwigPyObject_stype = 0; SWIGRUNTIME PyTypeObject* SwigPyObject_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type(); + assert(SwigPyObject_stype); + SwigPyClientData *cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; + assert(cd); + assert(cd->pytype); + return cd->pytype; +} +#else +SWIGRUNTIME PyTypeObject* +SwigPyObject_type(void) { + static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce(); return type; } +#endif SWIGRUNTIMEINLINE int SwigPyObject_Check(PyObject *op) { +#ifdef SWIGPYTHON_BUILTIN + PyTypeObject *target_tp = SwigPyObject_type(); + PyTypeObject *obj_tp; + if (PyType_IsSubtype(op->ob_type, target_tp)) + return 1; + return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0); +#else return (Py_TYPE(op) == SwigPyObject_type()) || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); +#endif } SWIGRUNTIME PyObject * @@ -630,9 +694,9 @@ SwigPyObject_getattr(SwigPyObject *sobj,char *name) #endif SWIGRUNTIME PyTypeObject* -_PySwigObject_type(void) { +SwigPyObject_TypeOnce(void) { static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; - + static PyNumberMethods SwigPyObject_as_number = { (binaryfunc)0, /*nb_add*/ (binaryfunc)0, /*nb_subtract*/ @@ -679,7 +743,7 @@ _PySwigObject_type(void) { #endif }; - static PyTypeObject swigpyobject_type; + static PyTypeObject swigpyobject_type; static int type_init = 0; if (!type_init) { const PyTypeObject tmp @@ -687,7 +751,7 @@ _PySwigObject_type(void) { /* PyObject header changed in Python 3 */ #if PY_VERSION_HEX >= 0x03000000 PyVarObject_HEAD_INIT(&PyType_Type, 0) -#else +#else PyObject_HEAD_INIT(NULL) 0, /* ob_size */ #endif @@ -697,17 +761,17 @@ _PySwigObject_type(void) { (destructor)SwigPyObject_dealloc, /* tp_dealloc */ (printfunc)SwigPyObject_print, /* tp_print */ #if PY_VERSION_HEX < 0x02020000 - (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ + (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ #else - (getattrfunc)0, /* tp_getattr */ + (getattrfunc)0, /* tp_getattr */ #endif - (setattrfunc)0, /* tp_setattr */ + (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 */ #else (cmpfunc)SwigPyObject_compare, /* tp_compare */ #endif - (reprfunc)SwigPyObject_repr, /* tp_repr */ + (reprfunc)SwigPyObject_repr, /* tp_repr */ &SwigPyObject_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -718,7 +782,7 @@ _PySwigObject_type(void) { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigobject_doc, /* tp_doc */ + swigobject_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)SwigPyObject_richcompare, /* tp_richcompare */ @@ -726,28 +790,31 @@ _PySwigObject_type(void) { #if PY_VERSION_HEX >= 0x02020000 0, /* tp_iter */ 0, /* tp_iternext */ - swigobject_methods, /* tp_methods */ + swigobject_methods, /* 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_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_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 */ +#endif #ifdef COUNT_ALLOCS 0,0,0,0 /* tp_alloc -> tp_next */ #endif @@ -831,17 +898,17 @@ SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); } -SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void); +SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void); SWIGRUNTIME PyTypeObject* SwigPyPacked_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type(); + static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce(); return type; } SWIGRUNTIMEINLINE int SwigPyPacked_Check(PyObject *op) { - return ((op)->ob_type == _PySwigPacked_type()) + return ((op)->ob_type == SwigPyPacked_TypeOnce()) || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); } @@ -856,10 +923,10 @@ SwigPyPacked_dealloc(PyObject *v) } SWIGRUNTIME PyTypeObject* -_PySwigPacked_type(void) { +SwigPyPacked_TypeOnce(void) { static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; static PyTypeObject swigpypacked_type; - static int type_init = 0; + static int type_init = 0; if (!type_init) { const PyTypeObject tmp = { @@ -901,28 +968,31 @@ _PySwigPacked_type(void) { #if PY_VERSION_HEX >= 0x02020000 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + 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_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_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 */ +#endif #ifdef COUNT_ALLOCS 0,0,0,0 /* tp_alloc -> tp_next */ #endif @@ -999,50 +1069,63 @@ SWIG_This(void) SWIGRUNTIME SwigPyObject * SWIG_Python_GetSwigThis(PyObject *pyobj) { - if (SwigPyObject_Check(pyobj)) { + PyObject *obj; + + if (SwigPyObject_Check(pyobj)) return (SwigPyObject *) pyobj; - } else { - PyObject *obj = 0; -#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) - if (PyInstance_Check(pyobj)) { - obj = _PyInstance_Lookup(pyobj, SWIG_This()); - } else { - PyObject **dictptr = _PyObject_GetDictPtr(pyobj); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; - } else { -#ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); - return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; - } + +#ifdef SWIGPYTHON_BUILTIN +# ifdef PyWeakref_CheckProxy + if (PyWeakref_CheckProxy(pyobj)) { + pyobj = PyWeakref_GET_OBJECT(pyobj); + if (pyobj && SwigPyObject_Check(pyobj)) + return (SwigPyObject*) pyobj; + } +# endif + return NULL; #endif - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } + + obj = 0; + +#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) + if (PyInstance_Check(pyobj)) { + obj = _PyInstance_Lookup(pyobj, SWIG_This()); + } else { + PyObject **dictptr = _PyObject_GetDictPtr(pyobj); + if (dictptr != NULL) { + PyObject *dict = *dictptr; + obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; + } else { +#ifdef PyWeakref_CheckProxy + if (PyWeakref_CheckProxy(pyobj)) { + PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); + return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; + } +#endif + obj = PyObject_GetAttr(pyobj,SWIG_This()); + if (obj) { + Py_DECREF(obj); + } else { + if (PyErr_Occurred()) PyErr_Clear(); + return 0; } } -#else - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } -#endif - if (obj && !SwigPyObject_Check(obj)) { - /* a PyObject is called 'this', try to get the 'real this' - SwigPyObject from it */ - return SWIG_Python_GetSwigThis(obj); - } - return (SwigPyObject *)obj; } +#else + obj = PyObject_GetAttr(pyobj,SWIG_This()); + if (obj) { + Py_DECREF(obj); + } else { + if (PyErr_Occurred()) PyErr_Clear(); + return 0; + } +#endif + if (obj && !SwigPyObject_Check(obj)) { + /* a PyObject is called 'this', try to get the 'real this' + SwigPyObject from it */ + return SWIG_Python_GetSwigThis(obj); + } + return (SwigPyObject *)obj; } /* Acquire a pointer value */ @@ -1064,91 +1147,97 @@ SWIG_Python_AcquirePtr(PyObject *obj, int own) { SWIGRUNTIME int SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { - if (!obj) return SWIG_ERROR; + int res; + SwigPyObject *sobj; + + if (!obj) + return SWIG_ERROR; if (obj == Py_None) { - if (ptr) *ptr = 0; + if (ptr) + *ptr = 0; return SWIG_OK; - } else { - SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); - if (own) - *own = 0; - while (sobj) { - void *vptr = sobj->ptr; - if (ty) { - swig_type_info *to = sobj->ty; - if (to == ty) { - /* no type cast needed */ - if (ptr) *ptr = vptr; - break; - } else { - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) { - sobj = (SwigPyObject *)sobj->next; - } else { - if (ptr) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ - if (own) - *own = *own | SWIG_CAST_NEW_MEMORY; - } - } - break; - } - } + } + + res = SWIG_ERROR; + + sobj = SWIG_Python_GetSwigThis(obj); + if (own) + *own = 0; + while (sobj) { + void *vptr = sobj->ptr; + if (ty) { + swig_type_info *to = sobj->ty; + if (to == ty) { + /* no type cast needed */ + if (ptr) *ptr = vptr; + break; } else { - if (ptr) *ptr = vptr; - break; + swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); + if (!tc) { + sobj = (SwigPyObject *)sobj->next; + } else { + if (ptr) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ + if (own) + *own = *own | SWIG_CAST_NEW_MEMORY; + } + } + break; + } } - } - if (sobj) { - if (own) - *own = *own | sobj->own; - if (flags & SWIG_POINTER_DISOWN) { - sobj->own = 0; - } - return SWIG_OK; } else { - int res = SWIG_ERROR; - if (flags & SWIG_POINTER_IMPLICIT_CONV) { - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - if (data && !data->implicitconv) { - PyObject *klass = data->klass; - if (klass) { - PyObject *impconv; - data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ - impconv = SWIG_Python_CallFunctor(klass, obj); - data->implicitconv = 0; - if (PyErr_Occurred()) { - PyErr_Clear(); - impconv = 0; - } - if (impconv) { - SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); - if (iobj) { - void *vptr; - res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); - if (SWIG_IsOK(res)) { - if (ptr) { - *ptr = vptr; - /* transfer the ownership to 'ptr' */ - iobj->own = 0; - res = SWIG_AddCast(res); - res = SWIG_AddNewMask(res); - } else { - res = SWIG_AddCast(res); - } - } - } - Py_DECREF(impconv); - } - } - } - } - return res; + if (ptr) *ptr = vptr; + break; } } + if (sobj) { + if (own) + *own = *own | sobj->own; + if (flags & SWIG_POINTER_DISOWN) { + sobj->own = 0; + } + res = SWIG_OK; + } else { + if (flags & SWIG_POINTER_IMPLICIT_CONV) { + SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; + if (data && !data->implicitconv) { + PyObject *klass = data->klass; + if (klass) { + PyObject *impconv; + data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ + impconv = SWIG_Python_CallFunctor(klass, obj); + data->implicitconv = 0; + if (PyErr_Occurred()) { + PyErr_Clear(); + impconv = 0; + } + if (impconv) { + SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); + if (iobj) { + void *vptr; + res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); + if (SWIG_IsOK(res)) { + if (ptr) { + *ptr = vptr; + /* transfer the ownership to 'ptr' */ + iobj->own = 0; + res = SWIG_AddCast(res); + res = SWIG_AddNewMask(res); + } else { + res = SWIG_AddCast(res); + } + } + } + Py_DECREF(impconv); + } + } + } + } + } + return res; } /* Convert a function ptr value */ @@ -1318,22 +1407,54 @@ SWIG_Python_InitShadowInstance(PyObject *args) { /* Create a new pointer object */ SWIGRUNTIME PyObject * -SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) { - if (!ptr) { +SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) { + SwigPyClientData *clientdata; + PyObject * robj; + int own; + + if (!ptr) return SWIG_Py_Void(); - } else { - int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; - PyObject *robj = SwigPyObject_New(ptr, type, own); - SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; - if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { - PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); - if (inst) { - Py_DECREF(robj); - robj = inst; + + clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; + own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; + if (clientdata && clientdata->pytype) { + SwigPyObject *newobj; + if (flags & SWIG_BUILTIN_TP_INIT) { + newobj = (SwigPyObject*) self; + if (newobj->ptr) { + PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0); + while (newobj->next) + newobj = (SwigPyObject *) newobj->next; + newobj->next = next_self; + newobj = (SwigPyObject *)next_self; } + } else { + newobj = PyObject_New(SwigPyObject, clientdata->pytype); } - return robj; + if (newobj) { + newobj->ptr = ptr; + newobj->ty = type; + newobj->own = own; + newobj->next = 0; +#ifdef SWIGPYTHON_BUILTIN + newobj->dict = 0; +#endif + return (PyObject*) newobj; + } + return SWIG_Py_Void(); } + + assert(!(flags & SWIG_BUILTIN_TP_INIT)); + + robj = SwigPyObject_New(ptr, type, own); + if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { + PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); + if (inst) { + Py_DECREF(robj); + robj = inst; + } + } + return robj; } /* Create a new packed object */ @@ -1562,7 +1683,7 @@ SWIG_Python_TypeError(const char *type, PyObject *obj) /* Convert a pointer value, signal an exception on a type mismatch */ SWIGRUNTIME void * -SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) { +SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) { void *result; if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { PyErr_Clear(); @@ -1576,6 +1697,57 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) return result; } +SWIGRUNTIME int +SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { + PyTypeObject *tp = obj->ob_type; + PyObject *descr; + PyObject *encoded_name; + descrsetfunc f; + int res; + +#ifdef Py_USING_UNICODE + if (PyString_Check(name)) { + name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL); + if (!name) + return -1; + } else if (!PyUnicode_Check(name)) { +#else + if (!PyString_Check(name)) { +#endif + PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); + return -1; + } else { + Py_INCREF(name); + } + + if (!tp->tp_dict) { + if (PyType_Ready(tp) < 0) + goto done; + } + + res = -1; + descr = _PyType_Lookup(tp, name); + f = NULL; + if (descr != NULL) + f = descr->ob_type->tp_descr_set; + if (!f) { + if (PyString_Check(name)) { + encoded_name = name; + Py_INCREF(name); + } else { + encoded_name = PyUnicode_AsUTF8String(name); + } + PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name)); + Py_DECREF(encoded_name); + } else { + res = f(descr, obj, value); + } + + done: + Py_DECREF(name); + return res; +} + #ifdef __cplusplus #if 0 diff --git a/Lib/python/pyruntime.swg b/Lib/python/pyruntime.swg index 00f15a144..dd22a1fdf 100644 --- a/Lib/python/pyruntime.swg +++ b/Lib/python/pyruntime.swg @@ -11,3 +11,6 @@ %insert(runtime) "pyapi.swg"; /* Python API */ %insert(runtime) "pyrun.swg"; /* Python run-time code */ +#if defined(SWIGPYTHON_BUILTIN) +%insert(runtime) "builtin.swg"; /* Specialization for classes with single inheritance */ +#endif \ No newline at end of file diff --git a/Lib/python/pystdcommon.swg b/Lib/python/pystdcommon.swg index 7e9720cc0..2f223a839 100644 --- a/Lib/python/pystdcommon.swg +++ b/Lib/python/pystdcommon.swg @@ -6,7 +6,7 @@ namespace swig { */ template struct traits_from_ptr { static PyObject *from(Type *val, int owner = 0) { - return SWIG_NewPointerObj(val, type_info(), owner); + return SWIG_InternalNewPointerObj(val, type_info(), owner); } }; diff --git a/Lib/python/pystrings.swg b/Lib/python/pystrings.swg index 1983037a5..f6a4eba8a 100644 --- a/Lib/python/pystrings.swg +++ b/Lib/python/pystrings.swg @@ -86,7 +86,7 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size) if (size > INT_MAX) { swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); return pchar_descriptor ? - SWIG_NewPointerObj(%const_cast(carray,char *), pchar_descriptor, 0) : SWIG_Py_Void(); + SWIG_InternalNewPointerObj(%const_cast(carray,char *), pchar_descriptor, 0) : SWIG_Py_Void(); } else { %#if PY_VERSION_HEX >= 0x03000000 return PyUnicode_FromStringAndSize(carray, %numeric_cast(size,int)); diff --git a/Lib/python/pytypemaps.swg b/Lib/python/pytypemaps.swg index 817ed1d90..c47a2ee93 100644 --- a/Lib/python/pytypemaps.swg +++ b/Lib/python/pytypemaps.swg @@ -51,7 +51,11 @@ #define SWIG_AppendOutput(result, obj) SWIG_Python_AppendOutput(result, obj) /* set constant */ -#define SWIG_SetConstant(name, obj) SWIG_Python_SetConstant(d, name,obj) +#if defined(SWIGPYTHON_BUILTIN) +#define SWIG_SetConstant(name, obj) SWIG_Python_SetConstant(d, d == md ? public_interface : NULL, name,obj) +#else +#define SWIG_SetConstant(name, obj) SWIG_Python_SetConstant(d, name,obj) +#endif /* raise */ #define SWIG_Raise(obj, type, desc) SWIG_Python_Raise(obj, type, desc) @@ -84,6 +88,12 @@ $result = SWIG_NewPointerObj(%new_copy(*$1, $*ltype), $descriptor, SWIG_POINTER_OWN | %newpointer_flags); } +/* +%typemap(builtin_init,noblock=1) const SWIGTYPE & SMARTPOINTER { + $result = SWIG_NewBuiltinObj(self, %new_copy(*$1, $*ltype), $descriptor, SWIG_POINTER_OWN | %newpointer_flags); +} +*/ + %typemap(ret,noblock=1) const SWIGTYPE & SMARTPOINTER, SWIGTYPE SMARTPOINTER { if ($result) { PyObject *robj = PyObject_CallMethod($result, (char *)"__deref__", NULL); @@ -95,4 +105,24 @@ } } +/* ------------------------------------------------------------- + * Output typemap for the __init__ method of a built-in type. + * ------------------------------------------------------------ */ +/* Pointers, references */ +/* +%typemap(builtin_init,noblock=1) SWIGTYPE *, SWIGTYPE &, SWIGTYPE[] { + %set_output(SWIG_Python_NewBuiltinObj(self, %as_voidptr($1), $descriptor, $owner | %newpointer_flags)); +} +*/ +/* +%typemap(builtin_init, noblock=1) SWIGTYPE *const& { + %set_output(SWIG_Python_NewBuiltinObj(self, %as_voidptr(*$1), $*descriptor, $owner | %newpointer_flags)); +} +*/ +/* Return by value */ +/* +%typemap(builtin_init, noblock=1) SWIGTYPE { + %set_output(SWIG_Python_NewBuiltinObj(self, %new_copy($1, $ltype), $&descriptor, $owner | %newpointer_flags)); +} +*/ diff --git a/Lib/python/pywstrings.swg b/Lib/python/pywstrings.swg index 7c36f248d..91f96d9e4 100644 --- a/Lib/python/pywstrings.swg +++ b/Lib/python/pywstrings.swg @@ -50,7 +50,7 @@ SWIG_FromWCharPtrAndSize(const wchar_t * carray, size_t size) 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) : SWIG_Py_Void(); + SWIG_InternalNewPointerObj(%const_cast(carray,wchar_t *), pwchar_descriptor, 0) : SWIG_Py_Void(); } else { return PyUnicode_FromWideChar(carray, %numeric_cast(size,int)); } diff --git a/Lib/python/std_map.i b/Lib/python/std_map.i index 074c43180..0c6681e3c 100644 --- a/Lib/python/std_map.i +++ b/Lib/python/std_map.i @@ -47,7 +47,7 @@ static PyObject *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); + return SWIG_InternalNewPointerObj(new map_type(map), desc, SWIG_POINTER_OWN); } else { SWIG_PYTHON_THREAD_BEGIN_BLOCK; size_type size = map.size(); @@ -119,6 +119,17 @@ return new SwigPyMapKeyIterator_T(current, begin, end, seq); } + template + inline PyObject* make_output_key_iterator_builtin (PyObject *pyself) + { + SwigPyObject *builtin_obj = (SwigPyObject*) pyself; + Sequence *seq = reinterpret_cast< Sequence * >(builtin_obj->ptr); + if (!seq) + return SWIG_Py_Void(); + SwigPyIterator *iter = make_output_key_iterator(seq->begin(), seq->begin(), seq->end(), pyself); + return SWIG_InternalNewPointerObj(iter, SWIGTYPE_p_swig__SwigPyIterator, SWIG_POINTER_OWN); + } + template > struct SwigPyMapValueITerator_T : SwigPyMapIterator_T @@ -136,6 +147,7 @@ { return new SwigPyMapValueITerator_T(current, begin, end, seq); } + } } @@ -143,6 +155,37 @@ %swig_sequence_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; + + %extend { + %newobject iterkeys(PyObject **PYTHON_SELF); + swig::SwigPyIterator* iterkeys(PyObject **PYTHON_SELF) { + return swig::make_output_key_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_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + } + + %newobject iteritems(PyObject **PYTHON_SELF); + swig::SwigPyIterator* iteritems(PyObject **PYTHON_SELF) { + return swig::make_output_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 __getitem__(const key_type& key) const throw (std::out_of_range) { Map::const_iterator i = self->find(key); @@ -151,7 +194,7 @@ 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()) @@ -236,21 +279,30 @@ swig::SwigPyIterator* value_iterator(PyObject **PYTHON_SELF) { return swig::make_output_value_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_map_methods(Map...) %swig_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); + } + } + %extend { void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) { (*self)[key] = x; } } + %enddef diff --git a/Lib/python/std_multimap.i b/Lib/python/std_multimap.i index 58336bc4b..8a240ae10 100644 --- a/Lib/python/std_multimap.i +++ b/Lib/python/std_multimap.i @@ -42,7 +42,7 @@ static PyObject *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); + return SWIG_InternalNewPointerObj(new multimap_type(multimap), desc, SWIG_POINTER_OWN); } else { size_type size = multimap.size(); int pysize = (size <= (size_type) INT_MAX) ? (int) size : -1; diff --git a/Lib/python/std_pair.i b/Lib/python/std_pair.i index bc8ccaade..782969574 100644 --- a/Lib/python/std_pair.i +++ b/Lib/python/std_pair.i @@ -116,9 +116,65 @@ } }; } + +#if defined(SWIGPYTHON_BUILTIN) +SWIGINTERN Py_ssize_t +SwigPython_std_pair_len (PyObject *a) +{ + return 2; } +SWIGINTERN PyObject* +SwigPython_std_pair_repr (PyObject *o) +{ + PyObject *tuple = PyTuple_New(2); + assert(tuple); + PyTuple_SET_ITEM(tuple, 0, PyObject_GetAttrString(o, (char*) "first")); + PyTuple_SET_ITEM(tuple, 1, PyObject_GetAttrString(o, (char*) "second")); + PyObject *result = PyObject_Repr(tuple); + Py_DECREF(tuple); + return result; +} + +SWIGINTERN PyObject* +SwigPython_std_pair_getitem (PyObject *a, Py_ssize_t b) +{ + PyObject *result = PyObject_GetAttrString(a, b % 2 ? (char*) "second" : (char*) "first"); + return result; +} + +SWIGINTERN int +SwigPython_std_pair_setitem (PyObject *a, Py_ssize_t b, PyObject *c) +{ + int result = PyObject_SetAttrString(a, b % 2 ? (char*) "second" : (char*) "first", c); + return result; +} +#endif + +} + +%feature("python:sq_length") std::pair "SwigPython_std_pair_len"; +%feature("python:sq_length") std::pair "SwigPython_std_pair_len"; +%feature("python:sq_length") std::pair "SwigPython_std_pair_len"; +%feature("python:sq_length") std::pair "SwigPython_std_pair_len"; + +%feature("python:tp_repr") std::pair "SwigPython_std_pair_repr"; +%feature("python:tp_repr") std::pair "SwigPython_std_pair_repr"; +%feature("python:tp_repr") std::pair "SwigPython_std_pair_repr"; +%feature("python:tp_repr") std::pair "SwigPython_std_pair_repr"; + +%feature("python:sq_item") std::pair "SwigPython_std_pair_getitem"; +%feature("python:sq_item") std::pair "SwigPython_std_pair_getitem"; +%feature("python:sq_item") std::pair "SwigPython_std_pair_getitem"; +%feature("python:sq_item") std::pair "SwigPython_std_pair_getitem"; + +%feature("python:sq_ass_item") std::pair "SwigPython_std_pair_setitem"; +%feature("python:sq_ass_item") std::pair "SwigPython_std_pair_setitem"; +%feature("python:sq_ass_item") std::pair "SwigPython_std_pair_setitem"; +%feature("python:sq_ass_item") std::pair "SwigPython_std_pair_setitem"; + %define %swig_pair_methods(pair...) +#if !defined(SWIGPYTHON_BUILTIN) %extend { %pythoncode {def __len__(self): return 2 def __repr__(self): return str((self.first, self.second)) @@ -133,6 +189,7 @@ def __setitem__(self, index, val): else: self.second = val} } +#endif %enddef %include diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 9ac50b2fb..b98793e0c 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -21,6 +21,7 @@ static int treduce = SWIG_cparse_template_reduce(0); #include #define PYSHADOW_MEMBER 0x2 +#define WARN_PYTHON_MULTIPLE_INH 405 static String *const_code = 0; static String *module = 0; @@ -31,6 +32,7 @@ static String *global_name = 0; static int shadow = 1; static int use_kw = 0; static int director_method_index = 0; +static int builtin = 0; static File *f_begin = 0; static File *f_runtime = 0; @@ -42,8 +44,15 @@ static File *f_directors_h = 0; static File *f_init = 0; static File *f_shadow_py = 0; static String *f_shadow = 0; -static String *f_shadow_imports = 0; +static Hash *f_shadow_imports = 0; +static String *f_shadow_builtin_imports = 0; static String *f_shadow_stubs = 0; +static Hash *builtin_getset = 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 *methods; static String *class_name; @@ -53,6 +62,7 @@ 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 py3 = 0; @@ -100,6 +110,7 @@ static const char *usage1 = (char *) "\ 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\ @@ -154,6 +165,78 @@ static const char *usage3 = (char *) "\ Function annotation \n\ \n"; +static String *getSlot(Node *n = NULL, const char *key = NULL) { + static String *slot_default = NewString("0"); + String *val = key && *key ? Getattr(n, key) : NULL; + return val ? val : slot_default; +} + +static void printSlot (File *f, DOH const *slotval, DOH const *slotname, DOH const *functype = NULL, bool comma=true) { + if (functype) + slotval = NewStringf("(%s) %s", functype, slotval); + int len = Len(slotval); + int fieldwidth = len > 40 ? 0 : 40 - len; + Printf(f, " %s%s%*s/* %s */\n", slotval, comma ? "," : "", fieldwidth, "", slotname); + if (functype) + Delete((DOH*) slotval); +} + +static String *getClosure(String *functype, String *wrapper, int funpack = 0) { + static const char *functypes[] = { + "unaryfunc", "SWIGPY_UNARYFUNC_CLOSURE", + "destructor", "SWIGPY_DESTRUCTOR_CLOSURE", + "inquiry", "SWIGPY_INQUIRY_CLOSURE", + "getiterfunc", "SWIGPY_UNARYFUNC_CLOSURE", + "binaryfunc", "SWIGPY_BINARYFUNC_CLOSURE", + "ternaryfunc", "SWIGPY_TERNARYFUNC_CLOSURE", + "lenfunc", "SWIGPY_LENFUNC_CLOSURE", + "ssizeargfunc", "SWIGPY_SSIZEARGFUNC_CLOSURE", + "ssizessizeargfunc", "SWIGPY_SSIZESSIZEARGFUNC_CLOSURE", + "ssizeobjargproc", "SWIGPY_SSIZEOBJARGPROC_CLOSURE", + "ssizessizeobjargproc", "SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE", + "objobjargproc", "SWIGPY_OBJOBJARGPROC_CLOSURE", + "reprfunc", "SWIGPY_REPRFUNC_CLOSURE", + "hashfunc", "SWIGPY_HASHFUNC_CLOSURE", + "iternextfunc", "SWIGPY_ITERNEXT_CLOSURE", + NULL + }; + + static const char *funpack_functypes[] = { + "unaryfunc", "SWIGPY_UNARYFUNC_CLOSURE", + "destructor", "SWIGPY_DESTRUCTOR_CLOSURE", + "inquiry", "SWIGPY_INQUIRY_CLOSURE", + "getiterfunc", "SWIGPY_UNARYFUNC_CLOSURE", + "ternaryfunc", "SWIGPY_TERNARYFUNC_CLOSURE", + "lenfunc", "SWIGPY_LENFUNC_CLOSURE", + "ssizeargfunc", "SWIGPY_FUNPACK_SSIZEARGFUNC_CLOSURE", + "ssizessizeargfunc", "SWIGPY_SSIZESSIZEARGFUNC_CLOSURE", + "ssizeobjargproc", "SWIGPY_SSIZEOBJARGPROC_CLOSURE", + "ssizessizeobjargproc", "SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE", + "objobjargproc", "SWIGPY_OBJOBJARGPROC_CLOSURE", + "reprfunc", "SWIGPY_REPRFUNC_CLOSURE", + "hashfunc", "SWIGPY_HASHFUNC_CLOSURE", + "iternextfunc", "SWIGPY_ITERNEXT_CLOSURE", + NULL + }; + + if (!functype) + return NULL; + char *c = Char(functype); + int i; + if (funpack) { + for (i = 0; funpack_functypes[i] != NULL; i += 2) { + if (!strcmp(c, funpack_functypes[i])) + return NewStringf("%s(%s)", funpack_functypes[i + 1], wrapper); + } + } else { + for (i = 0; functypes[i] != NULL; i += 2) { + if (!strcmp(c, functypes[i])) + return NewStringf("%s(%s)", functypes[i + 1], wrapper); + } + } + return NULL; +} + class PYTHON:public Language { public: PYTHON() { @@ -231,6 +314,7 @@ public: } } + /* ------------------------------------------------------------ * main() * ------------------------------------------------------------ */ @@ -430,6 +514,12 @@ public: } else if (strcmp(argv[i], "-py3") == 0) { py3 = 1; Swig_mark_arg(i); + } else if (strcmp(argv[i], "-builtin") == 0) { + if (CPlusPlus) { + builtin = 1; + Preprocessor_define("SWIGPYTHON_BUILTIN", 0); + } + Swig_mark_arg(i); } } @@ -529,6 +619,14 @@ public: f_wrappers = NewString(""); f_directors_h = NewString(""); f_directors = NewString(""); + builtin_getset = NewHash(); + class_members = NewHash(); + builtin_methods = NewString(""); + builtin_default_unref = NewString("delete $self;"); + + if (builtin) { + f_builtins = NewString(""); + } if (directorsEnabled()) { if (!no_header_file) { @@ -608,6 +706,10 @@ public: 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"); @@ -680,32 +782,28 @@ public: filen = NULL; f_shadow = NewString(""); - f_shadow_imports = NewString(""); + f_shadow_imports = NewHash(); + f_shadow_builtin_imports = NewString(""); f_shadow_stubs = NewString(""); Swig_register_filebyname("shadow", f_shadow); Swig_register_filebyname("python", f_shadow); - Swig_banner_target_lang(f_shadow, "#"); - - if (!modern) { - Printv(f_shadow, "# This file is compatible with both classic and new-style classes.\n", NIL); - } - if (mod_docstring && Len(mod_docstring)) { - Printv(f_shadow, "\n\"\"\"\n", mod_docstring, "\n\"\"\"\n", NIL); + Printv(f_shadow, "\"\"\"\n", mod_docstring, "\n\"\"\"\n\n", NIL); Delete(mod_docstring); mod_docstring = NULL; } Printv(f_shadow, "\nfrom sys import version_info\n", NULL); - if (fastproxy) { + if (!builtin && fastproxy) { Printv(f_shadow, "if 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 @@ -741,6 +839,9 @@ public: * module. */ Printv(f_shadow, "del version_info\n", NULL); + if (builtin) { + Printf(f_shadow, "from %s import *\n", module); + } 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", NULL); } @@ -807,11 +908,10 @@ public: Printv(f_shadow, "try:\n", tab4, "import weakref\n", tab4, "weakref_proxy = weakref.proxy\n", "except:\n", tab4, "weakref_proxy = lambda x: x\n", "\n\n", NIL); } - // Include some information in the code - Printf(f_header, "\n/*-----------------------------------------------\n @(target):= %s.so\n\ - ------------------------------------------------*/\n", module); - } + // Include some information in the code + Printf(f_header, "\n/*-----------------------------------------------\n @(target):= %s.so\n\ + ------------------------------------------------*/\n", module); Printf(f_header, "#if PY_VERSION_HEX >= 0x03000000\n"); Printf(f_header, "# define SWIG_init PyInit_%s\n\n", module); @@ -829,6 +929,13 @@ public: /* the method exported for replacement of new.instancemethod in Python 3 */ add_pyinstancemethod_new(); + if (builtin) { + SwigType *s = NewString("SwigPyObject"); + SwigType_add_pointer(s); + SwigType_remember(s); + Delete(s); + } + /* emit code */ Language::top(n); @@ -842,6 +949,14 @@ public: Append(methods, "};\n"); Printf(f_wrappers, "%s\n", methods); + Printf(f_wrappers, "#ifdef __cplusplus\n"); + Printf(f_wrappers, "} /* extern \"C\" */\n"); + Printf(f_wrappers, "#endif\n"); + + if (builtin) { + Dump(f_builtins, f_wrappers); + } + SwigType_emit_type_table(f_runtime, f_wrappers); Append(const_code, "{0, 0, 0, 0.0, 0, 0}};\n"); @@ -855,14 +970,14 @@ public: Printf(f_init, "#endif\n"); Printf(f_init, "}\n"); - Printf(f_wrappers, "#ifdef __cplusplus\n"); - Printf(f_wrappers, "}\n"); - Printf(f_wrappers, "#endif\n"); - if (shadow) { + Swig_banner_target_lang(f_shadow_py, "#"); + if (!modern) { + Printv(f_shadow, "# This file is compatible with both classic and new-style classes.\n", NIL); + } + Printv(f_shadow_py, "\n", f_shadow_builtin_imports, "\n", NIL); Printv(f_shadow_py, f_shadow, "\n", NIL); Printv(f_shadow_py, f_shadow_stubs, "\n", NIL); - Close(f_shadow_py); Delete(f_shadow_py); } @@ -881,10 +996,13 @@ public: } Dump(f_wrappers, f_begin); + if (builtin) + Printf(f_begin, "static PyTypeObject *builtin_bases[%d];\n\n", max_bases + 2); Wrapper_pretty_print(f_init, f_begin); Delete(f_header); Delete(f_wrappers); + Delete(f_builtins); Delete(f_init); Delete(f_directors); Delete(f_directors_h); @@ -937,13 +1055,13 @@ public: if (shadowimport) { if (!options || (!Getattr(options, "noshadow") && !Getattr(options, "noproxy"))) { Printf(import, "_%s\n", modname); - if (!Strstr(f_shadow_imports, import)) { + if (!GetFlagAttr(f_shadow_imports, import)) { if (pkg && (!package || Strcmp(pkg, package) != 0)) { - Printf(f_shadow, "import %s.%s\n", pkg, modname); + Printf(builtin ? f_shadow_builtin_imports : f_shadow, "import %s.%s\n", pkg, modname); } else { - Printf(f_shadow, "import %s\n", modname); + Printf(builtin ? f_shadow_builtin_imports : f_shadow, "import %s\n", modname); } - Printv(f_shadow_imports, import, NULL); + SetFlag(f_shadow_imports, import); } } } @@ -1132,6 +1250,21 @@ public: 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. + * ------------------------------------------------------------ */ + + String *cdocstring(Node *n, autodoc_t ad_type) + { + String *ds = docstring(n, ad_type, "", false); + Replaceall(ds, "\\", "\\\\"); + Replaceall(ds, "\"", "\\\""); + Replaceall(ds, "\n", "\\n\"\n\t\t\""); + return ds; } /* ----------------------------------------------------------------------------- @@ -1680,7 +1813,7 @@ 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) { if (!kw) { if (n && funpack) { if (num_required == 0 && num_arguments == 0) { @@ -1701,20 +1834,16 @@ public: Append(methods, "NULL"); } else if (Getattr(n, "feature:callback")) { if (have_docstring(n)) { - String *ds = docstring(n, AUTODOC_FUNC, "", false); - Replaceall(ds, "\\", "\\\\"); - Replaceall(ds, "\"", "\\\""); - Replaceall(ds, "\n", "\\n\"\n\t\t\""); + String *ds = cdocstring(n, AUTODOC_FUNC); Printf(methods, "(char *)\"%s\\nswig_ptr: %s\"", ds, Getattr(n, "feature:callback:name")); + Delete(ds); } else { Printf(methods, "(char *)\"swig_ptr: %s\"", Getattr(n, "feature:callback:name")); } } else if (have_docstring(n)) { - String *ds = docstring(n, AUTODOC_FUNC, "", false); - Replaceall(ds, "\\", "\\\\"); - Replaceall(ds, "\"", "\\\""); - Replaceall(ds, "\n", "\\n\"\n\t\t\""); + String *ds = cdocstring(n, AUTODOC_FUNC); Printf(methods, "(char *)\"%s\"", ds); + Delete(ds); } else { Append(methods, "NULL"); } @@ -1725,9 +1854,11 @@ public: /* ------------------------------------------------------------ * dispatchFunction() * ------------------------------------------------------------ */ - void dispatchFunction(Node *n, int funpack = 0) { + void dispatchFunction(Node *n, String *linkage, int funpack = 0, bool builtin_self = false, bool builtin_ctor = false, bool director_class = false) { /* Last node in overloaded chain */ + bool add_self = builtin_self && (!builtin_ctor || director_class); + int maxargs; String *tmp = NewString(""); @@ -1746,7 +1877,7 @@ public: String *symname = Getattr(n, "sym:name"); String *wname = Swig_name_wrapper(symname); - Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *self, PyObject *args) {", NIL); + Printv(f->def, linkage, builtin_ctor ? "int " : "PyObject *", wname, "(PyObject *self, PyObject *args) {", NIL); Wrapper_add_local(f, "argc", "int argc"); Printf(tmp, "PyObject *argv[%d]", maxargs + 1); @@ -1754,15 +1885,23 @@ public: if (!fastunpack) { Wrapper_add_local(f, "ii", "int ii"); - Append(f->code, "if (!PyTuple_Check(args)) SWIG_fail;\n"); - Append(f->code, "argc = (int)PyObject_Length(args);\n"); - Printf(f->code, "for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n", maxargs); - Append(f->code, "argv[ii] = PyTuple_GET_ITEM(args,ii);\n"); + if (maxargs - (add_self ? 1 : 0) > 0) + Append(f->code, "if (!PyTuple_Check(args)) SWIG_fail;\n"); + Append(f->code, "argc = args ? (int)PyObject_Length(args) : 0;\n"); + if (add_self) + Append(f->code, "argv[0] = self;\n"); + Printf(f->code, "for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n", add_self ? maxargs - 1 : maxargs); + Printf(f->code, "argv[ii%s] = PyTuple_GET_ITEM(args,ii);\n", add_self ? " + 1" : ""); Append(f->code, "}\n"); + if (add_self) + 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))) SWIG_fail;\n", iname, maxargs); - Append(f->code, "--argc;\n"); + 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 + Append(f->code, "--argc;\n"); } Replaceall(dispatch, "$args", "self,args"); @@ -1784,16 +1923,17 @@ public: Append(f->code, "fail:\n"); Printf(f->code, "SWIG_SetErrorMsg(PyExc_NotImplementedError," "\"Wrong number or type of arguments for overloaded function '%s'.\\n\"" "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes); - Append(f->code, "return NULL;\n"); + Printf(f->code, "return %s;\n", builtin_ctor ? "-1" : "0"); Delete(protoTypes); } Printv(f->code, "}\n", NIL); Wrapper_print(f, f_wrappers); Node *p = Getattr(n, "sym:previousSibling"); - add_method(symname, wname, 0, p); + if (!builtin_self) + add_method(symname, wname, 0, p); /* Create a shadow for this function (if enabled and not in a member function) */ - if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { + if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) { emitFunctionShadowHelper(n, f_shadow_stubs, symname, 0); } DelWrapper(f); @@ -1806,6 +1946,24 @@ public: * functionWrapper() * ------------------------------------------------------------ */ + /* + A note about argument marshalling with built-in types. + There are three distinct cases for member (non-static) methods: + + 1) An ordinary member function. In this case, the first param in + the param list is 'this'. For builtin types, 'this' is taken from + the first argument to the wrapper (usually called 'self); it's not + extracted from the second argument (which is usually a tuple). + + 2) A constructor for a non-director class. In this case, the + param list doesn't contain an entry for 'this', but the first ('self') + argument to the wrapper *does* contain the newly-allocated, + uninitialized object. + + 3) A constructor for a director class. In this case, the param + list contains a 'self' param, which comes from the first argument + to the wrapper function. + */ const char *get_implicitconv_flag(Node *klass) { int conv = 0; @@ -1822,12 +1980,15 @@ public: String *iname = Getattr(n, "sym:name"); SwigType *d = Getattr(n, "type"); ParmList *l = Getattr(n, "parms"); + Node *parent = Swig_methodclass(n); + int director_method = 0; Parm *p; int i; char source[64]; Wrapper *f; + String *self_parse; String *parse_args; String *arglist; String *get_pointers; @@ -1839,6 +2000,8 @@ public: int num_required; int num_arguments; + int tuple_required; + int tuple_arguments; int varargs = 0; int allow_kwargs = check_kwargs(n); @@ -1857,7 +2020,25 @@ public: handled_as_init = (Strcmp(nname, sname) == 0) || (Strcmp(nname, cname) == 0); Delete(cname); } - + bool builtin_self = builtin && in_class && (constructor || (l && Getattr(l, "self"))); + bool builtin_ctor = false; + if (builtin_self && constructor) { + String *class_mname = Getattr(getCurrentClass(), "sym:name"); + String *mrename = Swig_name_construct(getNSpace(), class_mname); + if (Cmp(iname, mrename)) + builtin_self = false; + else + builtin_ctor = true; + } + 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 "); + String *wrapper_name = Swig_name_wrapper(iname); if (Getattr(n, "sym:overloaded")) { overname = Getattr(n, "sym:overname"); @@ -1867,6 +2048,7 @@ public: } f = NewWrapper(); + self_parse = NewString(""); parse_args = NewString(""); arglist = NewString(""); get_pointers = NewString(""); @@ -1885,22 +2067,26 @@ public: emit_attach_parmmaps(l, f); Setattr(n, "wrap:parms", l); /* Get number of required and total arguments */ - num_arguments = emit_num_arguments(l); - num_required = emit_num_required(l); + tuple_arguments = num_arguments = emit_num_arguments(l); + tuple_required = num_required = emit_num_required(l); + if (add_self) { + --tuple_arguments; + --tuple_required; + } if (((num_arguments == 0) && (num_required == 0)) || ((num_arguments == 1) && (num_required == 1) && Getattr(l, "self"))) allow_kwargs = 0; varargs = emit_isvarargs(l); - String *wname = Swig_name_wrapper(iname); + String *wname = Copy(wrapper_name); if (overname) { Append(wname, overname); } - if (!allow_kwargs || Getattr(n, "sym:overloaded")) { + if (!allow_kwargs || overname) { if (!varargs) { - Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); } else { - Printv(f->def, "SWIGINTERN PyObject *", wname, "__varargs__", "(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *varargs) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "__varargs__", "(PyObject *", self_param, ", PyObject *args, PyObject *varargs) {", NIL); } if (allow_kwargs) { Swig_warning(WARN_LANG_OVERLOAD_KEYWORD, input_file, line_number, "Can't use keyword arguments with overloaded functions (%s).\n", Swig_name_decl(n)); @@ -1911,18 +2097,43 @@ public: Swig_warning(WARN_LANG_VARARGS_KEYWORD, input_file, line_number, "Can't wrap varargs with keyword arguments enabled\n"); varargs = 0; } - Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args, PyObject *kwargs) {", NIL); } - if (!allow_kwargs) { - Append(parse_args, " if (!PyArg_ParseTuple(args,(char *)\""); - } else { - Append(parse_args, " if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)\""); - Append(arglist, ",kwnames"); + if (!builtin || !in_class || tuple_arguments > 0) { + if (!allow_kwargs) { + Append(parse_args, " if (!PyArg_ParseTuple(args,(char *)\""); + } else { + Append(parse_args, " if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)\""); + Append(arglist, ",kwnames"); + } } - int funpack = modernargs && fastunpack && !varargs && !allow_kwargs; - int noargs = funpack && (num_required == 0 && num_arguments == 0); - int onearg = funpack && (num_required == 1 && num_arguments == 1); + 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; + } + + int funpack = modernargs && 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")) { + String *argattr = NewStringf("%d", tuple_arguments); + Setattr(n, "python:argcount", argattr); + Delete(argattr); + } /* Generate code for argument marshalling */ if (funpack) { @@ -1942,7 +2153,6 @@ public: if (constructor && num_arguments == 1 && num_required == 1) { if (Cmp(storage, "explicit") == 0) { - Node *parent = Swig_methodclass(n); if (GetFlag(parent, "feature:implicitconv")) { String *desc = NewStringf("SWIGTYPE%s", SwigType_manglestr(Getattr(n, "type"))); Printf(f->code, "if (SWIG_CheckImplicit(%s)) SWIG_fail;\n", desc); @@ -1951,9 +2161,18 @@ public: } } + if (builtin_ctor && checkAttribute(n, "access", "protected")) { + String *tmp_none_comparison = Copy(none_comparison); + Replaceall(tmp_none_comparison, "$arg", "self"); + Printf(self_parse, "if (!(%s)) {\n", tmp_none_comparison); + Printv(self_parse, " SWIG_SetErrorMsg(PyExc_RuntimeError, \"accessing abstract class or protected constructor\");\n SWIG_fail;\n}\n", NIL); + Delete(tmp_none_comparison); + } + int use_parse = 0; Append(kwargs, "{"); for (i = 0, p = l; i < num_arguments; i++) { + bool parse_from_tuple = (i > 0 || !add_self); while (checkAttribute(p, "tmap:in:numinputs", "0")) { p = Getattr(p, "tmap:in:next"); } @@ -1961,19 +2180,21 @@ public: SwigType *pt = Getattr(p, "type"); String *pn = Getattr(p, "name"); String *ln = Getattr(p, "lname"); - if (funpack) { - sprintf(source, "swig_obj[%d]", i); - } else { - sprintf(source, "obj%d", i); + if (!parse_from_tuple) + sprintf(source, "self"); + else if (funpack) + sprintf(source, "swig_obj[%d]", add_self && !overname ? i - 1 : i); + else + sprintf(source, "obj%d", builtin_ctor ? i + 1 : i); + + if (parse_from_tuple) { + Putc(',', arglist); + if (i == num_required) + Putc('|', parse_args); /* Optional argument separator */ } - - Putc(',', arglist); - if (i == num_required) - Putc('|', parse_args); /* Optional argument separator */ - /* Keyword argument handling */ - if (allow_kwargs) { + if (allow_kwargs && parse_from_tuple) { if (Len(pn)) { String *tmp = 0; String *name = pn; @@ -1992,7 +2213,9 @@ public: if ((tm = Getattr(p, "tmap:in"))) { String *parse = Getattr(p, "tmap:in:parse"); if (!parse) { - if (funpack) { + if (builtin_self) { + Replaceall(tm, "$self", "self"); + } else if (funpack) { Replaceall(tm, "$self", "swig_obj[0]"); } else { Replaceall(tm, "$self", "obj0"); @@ -2018,8 +2241,9 @@ public: Setattr(p, "implicitconv", convflag); } - Putc('O', parse_args); - if (!funpack) { + if (parse_from_tuple) + Putc('O', parse_args); + if (!funpack && parse_from_tuple) { Wrapper_add_localv(f, source, "PyObject *", source, "= 0", NIL); Printf(arglist, "&%s", source); } @@ -2032,7 +2256,8 @@ public: } else { use_parse = 1; Append(parse_args, parse); - Printf(arglist, "&%s", ln); + if (parse_from_tuple) + Printf(arglist, "&%s", ln); } p = Getattr(p, "tmap:in:next"); continue; @@ -2049,43 +2274,47 @@ public: } if (use_parse || allow_kwargs || !modernargs) { - Printf(parse_args, ":%s\"", iname); - Printv(parse_args, arglist, ")) SWIG_fail;\n", NIL); - funpack = 0; + if (builtin && in_class && tuple_arguments == 0) { + Printf(parse_args, " if (args && PyTuple_Check(args) && PyTuple_GET_SIZE(args) > 0) SWIG_fail;\n"); + } else { + Printf(parse_args, ":%s\"", iname); + Printv(parse_args, arglist, ")) SWIG_fail;\n", NIL); + funpack = 0; + } } else { Clear(parse_args); if (funpack) { Clear(f->def); if (overname) { if (noargs) { - Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), int nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL); } else { - Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), int nobjs, PyObject **swig_obj) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int 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, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); } else { - Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); } - if (onearg) { + if (onearg && !builtin_ctor) { Printf(parse_args, "if (!args) SWIG_fail;\n"); - Printf(parse_args, "swig_obj[0] = args;\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_required, num_arguments); + Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args,\"%s\",%d,%d,swig_obj)) SWIG_fail;\n", iname, tuple_required, tuple_arguments); } else if (noargs) { - Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args,\"%s\",%d,%d,0)) SWIG_fail;\n", iname, num_required, num_arguments); + Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args,\"%s\",%d,%d,0)) SWIG_fail;\n", iname, tuple_required, tuple_arguments); } } - } else { - Printf(parse_args, "if(!PyArg_UnpackTuple(args,(char *)\"%s\",%d,%d", iname, num_required, num_arguments); + } else if (tuple_arguments > 0) { + Printf(parse_args, "if(!PyArg_UnpackTuple(args,(char *)\"%s\",%d,%d", iname, tuple_required, tuple_arguments); Printv(parse_args, arglist, ")) SWIG_fail;\n", NIL); } } /* Now piece together the first part of the wrapper function */ - Printv(f->code, parse_args, get_pointers, NIL); + Printv(f->code, self_parse, parse_args, get_pointers, NIL); /* Check for trailing varargs */ if (varargs) { @@ -2176,9 +2405,11 @@ public: } Wrapper_add_local(f, "upcall", "bool upcall = false"); if (funpack) { - Append(f->code, "upcall = (director && (director->swig_get_self()==swig_obj[0]));\n"); + const char *self_parm = builtin_self ? "self" : "swig_obj[0]"; + Printf(f->code, "upcall = (director && (director->swig_get_self()==%s));\n", self_parm); } else { - Append(f->code, "upcall = (director && (director->swig_get_self()==obj0));\n"); + const char *self_parm = builtin_self ? "self" : "obj0"; + Printf(f->code, "upcall = (director && (director->swig_get_self()==%s));\n", self_parm); } } @@ -2211,8 +2442,12 @@ public: /* This part below still needs cleanup */ /* Return the function value */ - if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { - if (funpack) { + tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode); + + if (tm) { + if (builtin_self) { + Replaceall(tm, "$self", "self"); + } else if (funpack) { Replaceall(tm, "$self", "swig_obj[0]"); } else { Replaceall(tm, "$self", "obj0"); @@ -2220,7 +2455,9 @@ public: Replaceall(tm, "$source", "result"); Replaceall(tm, "$target", "resultobj"); Replaceall(tm, "$result", "resultobj"); - if (handled_as_init) { + if (builtin_ctor) { + Replaceall(tm, "$owner", "SWIG_BUILTIN_INIT"); + } else if (handled_as_init) { Replaceall(tm, "$owner", "SWIG_POINTER_NEW"); } else { if (GetFlag(n, "feature:new")) { @@ -2244,7 +2481,6 @@ public: String *type = Getattr(n, "type"); //Node *classNode = Swig_methodclass(n); //Node *module = Getattr(classNode, "module"); - Node *parent = Swig_methodclass(n); Node *module = Getattr(parent, "module"); Node *target = Swig_directormap(module, type); if (target) @@ -2305,7 +2541,10 @@ public: } } - Append(f->code, " return resultobj;\n"); + if (builtin_ctor) + Append(f->code, " return resultobj == Py_None ? 1 : 0;\n"); + else + Append(f->code, " return resultobj;\n"); /* Error handling code */ @@ -2313,7 +2552,10 @@ public: if (need_cleanup) { Printv(f->code, cleanup, NIL); } - Printv(f->code, " return NULL;\n", NIL); + if (builtin_ctor) + Printv(f->code, " return -1;\n", NIL); + else + Printv(f->code, " return NULL;\n", NIL); if (funpack) { @@ -2334,7 +2576,9 @@ public: Replaceall(f->code, "$symname", iname); Replaceall(f->code, "$result", "resultobj"); - if (funpack) { + if (builtin_self) { + Replaceall(f->code, "$self", "self"); + } else if (funpack) { Replaceall(f->code, "$self", "swig_obj[0]"); } else { Replaceall(f->code, "$self", "obj0"); @@ -2347,13 +2591,31 @@ public: if (varargs) { DelWrapper(f); f = NewWrapper(); - Printv(f->def, "SWIGINTERN PyObject *", wname, "(PyObject *self, PyObject *args) {", NIL); - Wrapper_add_local(f, "resultobj", "PyObject *resultobj"); + if (funpack) { + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **swig_obj) {", NIL); + } else { + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); + } + Wrapper_add_local(f, "resultobj", builtin_ctor ? "int resultobj" : "PyObject *resultobj"); Wrapper_add_local(f, "varargs", "PyObject *varargs"); Wrapper_add_local(f, "newargs", "PyObject *newargs"); - Printf(f->code, "newargs = PyTuple_GetSlice(args,0,%d);\n", num_arguments); - Printf(f->code, "varargs = PyTuple_GetSlice(args,%d,PyTuple_Size(args)+1);\n", num_arguments); - Printf(f->code, "resultobj = %s__varargs__(self,newargs,varargs);\n", wname); + if (funpack) { + Wrapper_add_local(f, "i", "int i"); + Printf(f->code, "newargs = PyTuple_New(%d);\n", num_arguments); + Printf(f->code, "for (i = 0; i < %d; ++i) {\n", num_arguments); + Printf(f->code, " PyTuple_SET_ITEM(newargs, i, swig_obj[i]);\n"); + Printf(f->code, " Py_XINCREF(swig_obj[i]);\n"); + Printf(f->code, "}\n"); + Printf(f->code, "varargs = PyTuple_New(nobjs > %d ? nobjs - %d : 0);\n", num_arguments, num_arguments); + Printf(f->code, "for (i = 0; i < nobjs - %d; ++i) {\n", num_arguments); + Printf(f->code, " PyTuple_SET_ITEM(newargs, i, swig_obj[i + %d]);\n", num_arguments); + Printf(f->code, " Py_XINCREF(swig_obj[i + %d]);\n", num_arguments); + Printf(f->code, "}\n"); + } else { + Printf(f->code, "newargs = PyTuple_GetSlice(args,0,%d);\n", num_arguments); + Printf(f->code, "varargs = PyTuple_GetSlice(args,%d,PyTuple_Size(args)+1);\n", num_arguments); + } + Printf(f->code, "resultobj = %s__varargs__(%s,newargs,varargs);\n", wname, builtin ? "self" : "NULL"); Append(f->code, "Py_XDECREF(newargs);\n"); Append(f->code, "Py_XDECREF(varargs);\n"); Append(f->code, "return resultobj;\n"); @@ -2363,18 +2625,86 @@ public: /* Now register the function with the interpreter. */ if (!Getattr(n, "sym:overloaded")) { - add_method(iname, wname, allow_kwargs, n, funpack, num_required, num_arguments); + if (!builtin_self) + add_method(iname, wname, allow_kwargs, n, funpack, num_required, num_arguments); /* Create a shadow for this function (if enabled and not in a member function) */ - if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { + if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) { emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, iname, allow_kwargs); } } else { if (!Getattr(n, "sym:nextSibling")) { - dispatchFunction(n, funpack); + dispatchFunction(n, linkage, funpack, builtin_self, builtin_ctor, director_class); } } + + // Put this in tp_init of the PyTypeObject + if (builtin_ctor) { + if ((director_method || !is_private(n)) && !Getattr(class_members, iname)) { + Setattr(class_members, iname, n); + if (!builtin_tp_init) + builtin_tp_init = Swig_name_wrapper(iname); + } + } + + /* If this is a builtin type, create a PyGetSetDef entry for this member variable. */ + if (builtin_getter) { + Hash *h = Getattr(builtin_getset, name); + if (!h) { + h = NewHash(); + Setattr(builtin_getset, name, h); + Delete(h); + } + Setattr(h, "getter", wrapper_name); + Delattr(n, "memberget"); + } + if (builtin_setter) { + Hash *h = Getattr(builtin_getset, name); + if (!h) { + h = NewHash(); + Setattr(builtin_getset, name, h); + Delete(h); + } + Setattr(h, "setter", wrapper_name); + Delattr(n, "memberset"); + } + + if (in_class && builtin) { + /* Handle operator overloads overloads for builtin types */ + String *slot = Getattr(n, "feature:python:slot"); + if (slot) { + 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); + if (closure_decl) { + if (!Getattr(n, "sym:overloaded") || !Getattr(n, "sym:nextSibling")) + Printv(f_wrappers, closure_decl, "\n\n", NIL); + Append(closure_name, "_closure"); + Delete(closure_decl); + } + if (func_type) { + String *s = NewStringf("(%s) %s", func_type, closure_name); + Delete(closure_name); + closure_name = s; + } + Setattr(parent, feature_name, closure_name); + Delete(feature_name); + Delete(closure_name); + } + + /* Handle comparison operators for builtin types */ + String *compare = Getattr(n, "feature:python:compare"); + if (compare) { + Hash *richcompare = Getattr(parent, "python:richcompare"); + assert(richcompare); + Setattr(richcompare, compare, wrapper_name); + } + } + + Delete(self_parse); Delete(parse_args); + Delete(linkage); Delete(arglist); Delete(get_pointers); Delete(cleanup); @@ -2382,6 +2712,7 @@ public: Delete(kwargs); Delete(wname); DelWrapper(f); + Delete(wrapper_name); return SWIG_OK; } @@ -2410,19 +2741,18 @@ public: Python dictionary. */ if (!have_globals) { - Printf(f_init, "\t PyDict_SetItemString(d,(char*)\"%s\", SWIG_globals());\n", global_name); + Printf(f_init, "\t PyDict_SetItemString(md,(char*)\"%s\", SWIG_globals());\n", global_name); + if (builtin) + Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", global_name); have_globals = 1; - if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { + if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) { Printf(f_shadow_stubs, "%s = %s.%s\n", global_name, module, global_name); } } int assignable = is_assignable(n); - if ((shadow) && !assignable) { - if (!in_class) { - Printf(f_shadow_stubs, "%s = %s.%s\n", iname, global_name, iname); - } - } + if (!builtin && shadow && !assignable && !in_class) + Printf(f_shadow_stubs, "%s = %s.%s\n", iname, global_name, iname); String *getname = Swig_name_get(NSPACE_TODO, iname); String *setname = Swig_name_set(NSPACE_TODO, iname); @@ -2432,6 +2762,11 @@ public: /* Create a function for setting the value of the variable */ if (assignable) { Setattr(n, "wrap:name", varsetname); + if (builtin && in_class) { + String *set_wrapper = Swig_name_wrapper(setname); + Setattr(n, "pybuiltin:setter", set_wrapper); + Delete(set_wrapper); + } Printf(setf->def, "SWIGINTERN int %s(PyObject *_val) {", varsetname); if ((tm = Swig_typemap_lookup("varin", n, name, 0))) { Replaceall(tm, "$source", "_val"); @@ -2463,9 +2798,16 @@ public: /* Create a function for getting the value of a variable */ Setattr(n, "wrap:name", vargetname); + if (builtin && in_class) { + String *get_wrapper = Swig_name_wrapper(getname); + Setattr(n, "pybuiltin:getter", get_wrapper); + Delete(get_wrapper); + } int addfail = 0; Printf(getf->def, "SWIGINTERN PyObject *%s(void) {", vargetname); Wrapper_add_local(getf, "pyobj", "PyObject *pyobj = 0"); + if (builtin) + Wrapper_add_local(getf, "self", "PyObject *self = 0"); if ((tm = Swig_typemap_lookup("varout", n, name, 0))) { Replaceall(tm, "$source", name); Replaceall(tm, "$target", "pyobj"); @@ -2486,7 +2828,10 @@ public: /* Now add this to the variable linking mechanism */ Printf(f_init, "\t SWIG_addvarlink(SWIG_globals(),(char*)\"%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 SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", iname); + } Delete(vargetname); Delete(varsetname); Delete(getname); @@ -2520,6 +2865,7 @@ public: Delete(str); value = wname; } + if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) { Replaceall(tm, "$source", value); Replaceall(tm, "$target", name); @@ -2528,6 +2874,12 @@ public: Delete(tm); have_tm = 1; } + + if (builtin && in_class) { + Swig_require("builtin_constantWrapper", n, "*sym:name", "pybuiltin:symname", NIL); + Setattr(n, "sym:name", Getattr(n, "pybuiltin:symname")); + } + if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) { Replaceall(tm, "$source", value); Replaceall(tm, "$target", name); @@ -2536,11 +2888,16 @@ public: Delete(tm); have_tm = 1; } + + if (builtin && in_class) + Swig_restore(n); + if (!have_tm) { Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n"); return SWIG_NOWRAP; } - if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) { + + if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) { if (!in_class) { Printv(f_shadow, iname, " = ", module, ".", iname, "\n", NIL); } else { @@ -2565,7 +2922,7 @@ public: return SWIG_ERROR; add_method(name, wrapname, 0); - if (shadow) { + if (!builtin && shadow) { Printv(f_shadow_stubs, name, " = ", module, ".", name, "\n", NIL); } return SWIG_OK; @@ -2573,17 +2930,17 @@ public: -/* ---------------------------------------------------------------------------- - * BEGIN C++ Director Class modifications - * ------------------------------------------------------------------------- */ + /* ---------------------------------------------------------------------------- + * BEGIN C++ Director Class modifications + * ------------------------------------------------------------------------- */ -/* C++/Python polymorphism demo code, copyright (C) 2002 Mark Rose - * - * TODO - * - * Move some boilerplate code generation to Swig_...() functions. - * - */ + /* C++/Python polymorphism demo code, copyright (C) 2002 Mark Rose + * + * TODO + * + * Move some boilerplate code generation to Swig_...() functions. + * + */ /* --------------------------------------------------------------- * classDirectorMethod() @@ -2710,8 +3067,8 @@ public: Printf(f_directors_h, " return (iv != swig_inner.end() ? iv->second : false);\n"); Printf(f_directors_h, " }\n\n"); - Printf(f_directors_h, " void swig_set_inner(const char* swig_protected_method_name, bool swig_val) const\n"); - Printf(f_directors_h, " { swig_inner[swig_protected_method_name] = swig_val;}\n\n"); + Printf(f_directors_h, " void swig_set_inner(const char* swig_protected_method_name, bool val) const\n"); + Printf(f_directors_h, " { swig_inner[swig_protected_method_name] = val;}\n\n"); Printf(f_directors_h, "private:\n"); Printf(f_directors_h, " mutable std::map swig_inner;\n"); @@ -2757,24 +3114,30 @@ public: result = Language::classDirectorDisown(n); shadow = oldshadow; if (shadow) { - String *symname = Getattr(n, "sym:name"); - String *mrename = Swig_name_disown(NSPACE_TODO, symname); //Getattr(n, "name")); - Printv(f_shadow, tab4, "def __disown__(self):\n", NIL); + if (builtin) { + String *rname = SwigType_namestr(real_classname); + Printf(builtin_methods, tab4 "{ \"__disown__\", (PyCFunction) Swig::Director::swig_pyobj_disown< %s >, METH_NOARGS, \"\" },\n", rname); + Delete(rname); + } else { + String *symname = Getattr(n, "sym:name"); + String *mrename = Swig_name_disown(NSPACE_TODO, symname); //Getattr(n, "name")); + Printv(f_shadow, tab4, "def __disown__(self):\n", NIL); #ifdef USE_THISOWN - Printv(f_shadow, tab8, "self.thisown = 0\n", NIL); + Printv(f_shadow, tab8, "self.thisown = 0\n", NIL); #else - Printv(f_shadow, tab8, "self.this.disown()\n", NIL); + 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); - Delete(mrename); + Printv(f_shadow, tab8, module, ".", mrename, "(self)\n", NIL); + Printv(f_shadow, tab8, "return weakref_proxy(self)\n", NIL); + Delete(mrename); + } } return result; } -/* ---------------------------------------------------------------------------- - * END of C++ Director Class modifications - * ------------------------------------------------------------------------- */ + /* ---------------------------------------------------------------------------- + * END of C++ Director Class modifications + * ------------------------------------------------------------------------- */ /* ------------------------------------------------------------ @@ -2800,17 +3163,388 @@ public: Setattr(n, "python:proxy", importname); } } - return Language::classDeclaration(n); + int result = Language::classDeclaration(n); + return result; } /* ------------------------------------------------------------ * classHandler() * ------------------------------------------------------------ */ + String *add_explicit_scope(String *s) { + if (!Strstr(s, "::")) { + String *ss = NewStringf("::%s", s); + Delete(s); + s = ss; + } + return s; + } + + void builtin_pre_decl(Node *n) { + String *name = Getattr(n, "name"); + String *rname = add_explicit_scope(SwigType_namestr(name)); + String *mname = SwigType_manglestr(rname); + + Printf(f_init, "\n/* type '%s' */\n", rname); + Printf(f_init, " builtin_pytype = (PyTypeObject *)&SwigPyBuiltin_%s_type;\n", mname); + Printf(f_init, " builtin_pytype->tp_dict = d = PyDict_New();\n"); + + Delete(rname); + Delete(mname); + } + + void builtin_post_decl(File *f, Node *n) { + String *name = Getattr(n, "name"); + String *pname = Copy(name); + SwigType_add_pointer(pname); + String *symname = Getattr(n, "sym:name"); + String *rname = add_explicit_scope(SwigType_namestr(name)); + String *mname = SwigType_manglestr(rname); + String *pmname = SwigType_manglestr(pname); + String *templ = NewStringf("SwigPyBuiltin_%s", mname); + int funpack = modernargs && fastunpack; + + Printv(f_init, " SwigPyBuiltin_SetMetaType(builtin_pytype, metatype);\n", NIL); + Printf(f_init, " builtin_pytype->tp_new = PyType_GenericNew;\n"); + Printv(f_init, " builtin_base_count = 0;\n", NIL); + List *baselist = Getattr(n, "bases"); + if (baselist) { + int base_count = 0; + for (Iterator b = First(baselist); b.item; b = Next(b)) { + String *bname = Getattr(b.item, "name"); + if (!bname || GetFlag(b.item, "feature:ignore")) + continue; + base_count++; + String *base_name = Copy(bname); + SwigType_add_pointer(base_name); + String *base_mname = SwigType_manglestr(base_name); + Printf(f_init, " builtin_basetype = SWIG_MangledTypeQuery(\"%s\");\n", base_mname); + Printv(f_init, " if (builtin_basetype && builtin_basetype->clientdata && ((SwigPyClientData*) builtin_basetype->clientdata)->pytype) {\n", NIL); + Printv(f_init, " builtin_bases[builtin_base_count++] = ((SwigPyClientData*) builtin_basetype->clientdata)->pytype;\n", NIL); + Printv(f_init, " }\n", NIL); + Delete(base_name); + Delete(base_mname); + } + if (base_count > max_bases) + max_bases = base_count; + } + Printv(f_init, " builtin_bases[builtin_base_count] = NULL;\n", NIL); + Printv(f_init, " SwigPyBuiltin_InitBases(builtin_pytype, builtin_bases);\n", NIL); + + // Check for non-public destructor, in which case tp_dealloc will issue + // a warning and allow the memory to leak. Any class that doesn't explicitly + // have a private/protected destructor has an implicit public destructor. + String *tp_dealloc = Getattr(n, "feature:python:tp_dealloc"); + if (tp_dealloc) { + Printf(f, "SWIGPY_DESTRUCTOR_CLOSURE(%s);\n", tp_dealloc); + tp_dealloc = NewStringf("%s_closure", tp_dealloc); + } else { + tp_dealloc = NewString("SwigPyBuiltin_BadDealloc"); + } + + String *getset_name = NewStringf("%s_getset", templ); + String *methods_name = NewStringf("%s_methods", templ); + String *getset_def = NewString(""); + Printf(getset_def, "SWIGINTERN PyGetSetDef %s[] = {\n", getset_name); + + // All objects have 'this' and 'thisown' attributes + Printv(f_init, "PyDict_SetItemString(d, \"this\", this_descr);\n", NIL); + Printv(f_init, "PyDict_SetItemString(d, \"thisown\", thisown_descr);\n", NIL); + + // Now, the rest of the attributes + for (Iterator member_iter = First(builtin_getset); member_iter.item; member_iter = Next(member_iter)) { + String *memname = member_iter.key; + Hash *mgetset = member_iter.item; + String *getter = Getattr(mgetset, "getter"); + String *setter = Getattr(mgetset, "setter"); + const char *getter_closure = getter ? funpack ? "SwigPyBuiltin_FunpackGetterClosure" : "SwigPyBuiltin_GetterClosure" : "0"; + 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("{ const_cast(\"%s\"), (getter) %s, (setter) %s, const_cast(\"%s.%s\"), (void*) &%s }\n", memname, getter_closure, + setter_closure, name, memname, 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); + Printf(f_init, "PyDict_SetItemString(d, static_getset->d_getset->name, (PyObject*) static_getset);\n", memname); + Printf(f_init, "Py_DECREF(static_getset);\n"); + } else { + Printf(getset_def, " %s,\n", entry); + } + Delete(gspair); + Delete(entry); + } + Printv(f, getset_def, " {NULL} /* Sentinel */\n", "};\n\n", NIL); + + // Rich compare function + Hash *richcompare = Getattr(n, "python:richcompare"); + String *richcompare_func = NewStringf("%s_richcompare", templ); + assert(richcompare); + Printf(f, "SWIGINTERN PyObject *\n"); + Printf(f, "%s(PyObject *self, PyObject *other, int op) {\n", richcompare_func); + Printf(f, " PyObject *result = NULL;\n"); + if (!funpack) { + Printf(f, " PyObject *tuple = PyTuple_New(1);\n"); + Printf(f, " assert(tuple);\n"); + Printf(f, " PyTuple_SET_ITEM(tuple, 0, other);\n"); + Printf(f, " Py_XINCREF(other);\n"); + } + Printf(f, " switch (op) {\n"); + for (Iterator i = First(richcompare); i.item; i = Next(i)) + Printf(f, " case %s : result = %s(self, %s); break;\n", i.key, i.item, funpack ? "other" : "tuple"); + Printv(f, " default : break;\n", NIL); + Printf(f, " }\n"); + Printv(f, " if (!result) {\n", NIL); + Printv(f, " if (SwigPyObject_Check(self) && SwigPyObject_Check(other)) {\n", NIL); + Printv(f, " result = SwigPyObject_richcompare((SwigPyObject *)self, (SwigPyObject *)other, op);\n", NIL); + Printv(f, " } else {\n", NIL); + Printv(f, " result = Py_NotImplemented;\n", NIL); + Printv(f, " Py_INCREF(result);\n", NIL); + Printv(f, " }\n", NIL); + Printv(f, " }\n", NIL); + if (!funpack) + Printf(f, " Py_DECREF(tuple);\n"); + Printf(f, " return result;\n"); + Printf(f, "}\n\n"); + + // Methods + Printf(f, "SWIGINTERN PyMethodDef %s_methods[] = {\n", templ); + Dump(builtin_methods, f); + Printf(f, " {NULL} // Sentinel\n};\n\n"); + + // No instance dict for nondynamic objects + if (GetFlag(n, "feature:python:nondynamic")) + Setattr(n, "feature:python:tp_setattro", "SWIG_Python_NonDynamicSetAttr"); + + String *quoted_symname = NewStringf("\"%s\"", symname); + String *quoted_rname = NewStringf("\"%s\"", rname); + char const *tp_init = builtin_tp_init ? Char(builtin_tp_init) : Swig_directorclass(n) ? "0" : "SwigPyBuiltin_BadInit"; + String *tp_flags = NewString("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES"); + String *py3_tp_flags = NewString("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE"); + + + Printf(f, "static PyHeapTypeObject %s_type = {\n", templ); + + // PyTypeObject ht_type + Printf(f, " {\n"); + Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); + Printv(f, " PyVarObject_HEAD_INIT(&PyType_Type, 0)\n", NIL); + Printv(f, "#else\n", NIL); + Printf(f, " PyObject_HEAD_INIT(NULL)\n"); + printSlot(f, getSlot(), "ob_size"); + Printv(f, "#endif\n", NIL); + printSlot(f, quoted_symname, "tp_name"); + printSlot(f, "sizeof(SwigPyObject)", "tp_basicsize"); + printSlot(f, getSlot(n, "feature:python:tp_itemsize"), "tp_itemsize"); + printSlot(f, tp_dealloc, "tp_dealloc", "destructor"); + printSlot(f, getSlot(n, "feature:python:tp_print"), "tp_print", "printfunc"); + printSlot(f, getSlot(n, "feature:python:tp_getattr"), "tp_getattr", "getattrfunc"); + printSlot(f, getSlot(n, "feature:python:tp_setattr"), "tp_setattr", "setattrfunc"); + Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); + printSlot(f, getSlot(n, "feature:python:tp_compare"), "tp_compare"); + Printv(f, "#else\n", NIL); + printSlot(f, getSlot(n, "feature:python:tp_compare"), "tp_compare", "cmpfunc"); + Printv(f, "#endif\n", NIL); + printSlot(f, getSlot(n, "feature:python:tp_repr"), "tp_repr", "reprfunc"); + Printf(f, " &%s_type.as_number, /*tp_as_number*/\n", templ); + Printf(f, " &%s_type.as_sequence, /*tp_as_sequence*/\n", templ); + Printf(f, " &%s_type.as_mapping, /*tp_as_mapping*/\n", templ); + printSlot(f, getSlot(n, "feature:python:tp_hash"), "tp_hash", "hashfunc"); + printSlot(f, getSlot(n, "feature:python:tp_call"), "tp_call", "ternaryfunc"); + printSlot(f, getSlot(n, "feature:python:tp_str"), "tp_str", "reprfunc"); + printSlot(f, getSlot(n, "feature:python:tp_getattro"), "tp_getattro", "getattrofunc"); + printSlot(f, getSlot(n, "feature:python:tp_setattro"), "tp_setattro", "setattrofunc"); + Printf(f, " &%s_type.as_buffer, /*tp_as_buffer*/\n", templ); + Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); + printSlot(f, py3_tp_flags, "tp_flags"); + Printv(f, "#else\n", NIL); + printSlot(f, tp_flags, "tp_flags"); + Printv(f, "#endif\n", NIL); + printSlot(f, quoted_rname, "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, richcompare_func, "feature:python:tp_richcompare", "richcmpfunc"); + printSlot(f, getSlot(n, "feature:python:tp_weaklistoffset"), "tp_weaklistoffset"); + printSlot(f, getSlot(n, "feature:python:tp_iter"), "tp_iter", "getiterfunc"); + printSlot(f, getSlot(n, "feature:python:tp_iternext"), "tp_iternext", "iternextfunc"); + printSlot(f, methods_name, "tp_methods"); + printSlot(f, getSlot(n, "feature:python:tp_members"), "tp_members"); + printSlot(f, getset_name, " tp_getset"); + printSlot(f, getSlot(n, "feature:python:tp_base"), "tp_base"); + printSlot(f, getSlot(n, "feature:python:tp_dict"), "tp_dict"); + printSlot(f, getSlot(n, "feature:python:tp_descr_get"), "tp_descr_get", "descrgetfunc"); + printSlot(f, getSlot(n, "feature:python:tp_descr_set"), "tp_descr_set", "descrsetfunc"); + Printf(f, " (size_t)(((char*)&((SwigPyObject *) 64L)->dict) - (char*) 64L), /* tp_dictoffset */\n"); + printSlot(f, tp_init, "tp_init", "initproc"); + printSlot(f, getSlot(n, "feature:python:tp_alloc"), "tp_alloc", "allocfunc"); + printSlot(f, "0", "tp_new", "newfunc"); + printSlot(f, getSlot(n, "feature:python:tp_free"), "tp_free", "freefunc"); + Printf(f, " },\n"); + + // PyNumberMethods as_number + Printf(f, " {\n"); + printSlot(f, getSlot(n, "feature:python:nb_add"), "nb_add", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_subtract"), "nb_subtract", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_multiply"), "nb_multiply", "binaryfunc"); + Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_divide"), "nb_divide", "binaryfunc"); + Printv(f, "#endif\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_remainder"), "nb_remainder", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_divmod"), "nb_divmod", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_power"), "nb_power", "ternaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_negative"), "nb_negative", "unaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_positive"), "nb_positive", "unaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_absolute"), "nb_absolute", "unaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_nonzero"), "nb_nonzero", "inquiry"); + printSlot(f, getSlot(n, "feature:python:nb_invert"), "nb_invert", "unaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_lshift"), "nb_lshift", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_rshift"), "nb_rshift", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_and"), "nb_and", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_xor"), "nb_xor", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_or"), "nb_or", "binaryfunc"); + Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_coerce"), "nb_coerce", "coercion"); + Printv(f, "#endif\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_int"), "nb_int", "unaryfunc"); + Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_reserved"), "nb_reserved", "void*"); + Printv(f, "#else\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_long"), "nb_long", "unaryfunc"); + Printv(f, "#endif\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_float"), "nb_float", "unaryfunc"); + Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_oct"), "nb_oct", "unaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_hex"), "nb_hex", "unaryfunc"); + Printv(f, "#endif\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_inplace_add"), "nb_inplace_add", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_inplace_subtract"), "nb_inplace_subtract", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_inplace_multiply"), "nb_inplace_multiply", "binaryfunc"); + Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_inplace_divide"), "nb_inplace_divide", "binaryfunc"); + Printv(f, "#endif\n", NIL); + printSlot(f, getSlot(n, "feature:python:nb_inplace_remainder"), "nb_inplace_remainder", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_inplace_power"), "nb_inplace_power", "ternaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_inplace_lshift"), "nb_inplace_lshift", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_inplace_rshift"), "nb_inplace_rshift", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_inplace_and"), "nb_inplace_and", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_inplace_xor"), "nb_inplace_xor", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_inplace_or"), "nb_inplace_or", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_floor_divide"), "nb_floor_divide", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:nb_true_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_true_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); + Printf(f, " },\n"); + + // PyMappingMethods as_mapping; + Printf(f, " {\n"); + printSlot(f, getSlot(n, "feature:python:mp_length"), "mp_length", "lenfunc"); + printSlot(f, getSlot(n, "feature:python:mp_subscript"), "mp_subscript", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:mp_ass_subscript"), " mp_ass_subscript", "objobjargproc"); + Printf(f, " },\n"); + + // PySequenceMethods as_sequence; + Printf(f, " {\n"); + printSlot(f, getSlot(n, "feature:python:sq_length"), "sq_length", "lenfunc"); + printSlot(f, getSlot(n, "feature:python:sq_concat"), "sq_concat", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:sq_repeat"), "sq_repeat", "ssizeargfunc"); + printSlot(f, getSlot(n, "feature:python:sq_item"), "sq_item", "ssizeargfunc"); + Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); + printSlot(f, getSlot(n, "feature:was_sq_slice"), "was_sq_slice", "void*"); + Printv(f, "#else\n", NIL); + printSlot(f, getSlot(n, "feature:python:sq_slice"), "sq_slice", "ssizessizeargfunc"); + Printv(f, "#endif\n", NIL); + printSlot(f, getSlot(n, "feature:python:sq_ass_item"), "sq_ass_item", "ssizeobjargproc"); + Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); + printSlot(f, getSlot(n, "feature:was_sq_ass_slice"), "was_sq_ass_slice", "void*"); + Printv(f, "#else\n", NIL); + printSlot(f, getSlot(n, "feature:python:sq_ass_slice"), "sq_ass_slice", "ssizessizeobjargproc"); + Printv(f, "#endif\n", NIL); + printSlot(f, getSlot(n, "feature:python:sq_contains"), "sq_contains", "objobjproc"); + printSlot(f, getSlot(n, "feature:python:sq_inplace_concat"), "sq_inplace_concat", "binaryfunc"); + printSlot(f, getSlot(n, "feature:python:sq_inplace_repeat"), "sq_inplace_repeat", "ssizeargfunc"); + Printf(f, " },\n"); + + // PyBufferProcs as_buffer; + Printf(f, " {\n"); + Printv(f, "#if PY_VERSION_HEX >= 0x03000000\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, "#else\n", NIL); + printSlot(f, getSlot(n, "feature:python:bf_getreadbuffer"), "bf_getreadbuffer", "readbufferproc"); + printSlot(f, getSlot(n, "feature:python:bf_getwritebuffer"), "bf_getwritebuffer", "writebufferproc"); + 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); + Printf(f, " },\n"); + + // PyObject *ht_name, *ht_slots + printSlot(f, getSlot(n, "feature:python:ht_name"), "ht_name", "PyObject*"); + printSlot(f, getSlot(n, "feature:python:ht_slots"), "ht_slots", "PyObject*"); + Printf(f, "};\n\n"); + + String *clientdata = NewString(""); + Printf(clientdata, "&%s_clientdata", templ); + SwigType_remember_mangleddata(pmname, clientdata); + + String *smartptr = Getattr(n, "feature:smartptr"); + if (smartptr) { + SwigType *spt = Swig_cparse_type(smartptr); + SwigType *smart = SwigType_typedef_resolve_all(spt); + SwigType_add_pointer(smart); + String *smart_pmname = SwigType_manglestr(smart); + SwigType_remember_mangleddata(smart_pmname, clientdata); + Delete(spt); + Delete(smart); + Delete(smart_pmname); + } + + String *clientdata_klass = NewString("0"); + if (GetFlag(n, "feature:implicitconv")) { + Clear(clientdata_klass); + Printf(clientdata_klass, "(PyObject*) &%s_type", templ); + } + + Printf(f, "SWIGINTERN SwigPyClientData %s_clientdata = {%s, 0, 0, 0, 0, 0, (PyTypeObject *)&%s_type};\n\n", templ, clientdata_klass, templ); + + Printv(f_init, " if (PyType_Ready(builtin_pytype) < 0) {\n", NIL); + Printf(f_init, " PyErr_SetString(PyExc_TypeError, \"Couldn't create type '%s'\");\n", symname); + Printv(f_init, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); + Printv(f_init, " return NULL;\n", NIL); + Printv(f_init, "#else\n", NIL); + Printv(f_init, " return;\n", NIL); + Printv(f_init, "#endif\n", NIL); + Printv(f_init, " }\n", NIL); + Printv(f_init, " Py_INCREF(builtin_pytype);\n", NIL); + Printf(f_init, " PyModule_AddObject(m, \"%s\", (PyObject*) builtin_pytype);\n", symname); + Printf(f_init, " SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", symname); + Printv(f_init, " d = md;\n", NIL); + + Delete(clientdata); + Delete(rname); + Delete(pname); + Delete(mname); + Delete(pmname); + Delete(templ); + Delete(tp_dealloc); + Delete(tp_flags); + Delete(py3_tp_flags); + Delete(quoted_symname); + Delete(quoted_rname); + Delete(clientdata_klass); + Delete(richcompare_func); + Delete(getset_name); + Delete(methods_name); + } + virtual int classHandler(Node *n) { int oldclassic = classic; int oldmodern = modern; File *f_shadow_file = f_shadow; + Node *base_node = NULL; if (shadow) { @@ -2831,14 +3565,22 @@ public: modern = 0; } - shadow_indent = (String *) tab4; - class_name = Getattr(n, "sym:name"); real_classname = Getattr(n, "name"); if (!addSymbol(class_name, n)) return SWIG_ERROR; + if (builtin) { + List *baselist = Getattr(n, "bases"); + if (baselist && Len(baselist) > 0) { + Iterator b = First(baselist); + base_node = b.item; + } + } + + shadow_indent = (String *) tab4; + /* Handle inheritance */ String *base_class = NewString(""); List *baselist = Getattr(n, "bases"); @@ -2865,6 +3607,18 @@ public: } } + if (builtin) { + Hash *base_richcompare = NULL; + Hash *richcompare = NULL; + if (base_node) + base_richcompare = Getattr(base_node, "python:richcompare"); + if (base_richcompare) + richcompare = Copy(base_richcompare); + else + richcompare = NewHash(); + Setattr(n, "python:richcompare", richcompare); + } + /* dealing with abstract base class */ String *abcs = Getattr(n, "feature:python:abc"); if (py3 && abcs) { @@ -2874,49 +3628,59 @@ public: Printv(base_class, abcs, NIL); } - Printv(f_shadow, "class ", class_name, NIL); - - if (Len(base_class)) { - Printf(f_shadow, "(%s)", base_class); + if (builtin) { + if (have_docstring(n)) { + String *str = cdocstring(n, AUTODOC_CLASS); + Setattr(n, "feature:python:tp_doc", str); + Delete(str); + } } else { - if (!classic) { - Printf(f_shadow, modern ? "(object)" : "(_object)"); - } - if (GetFlag(n, "feature:exceptionclass")) { - Printf(f_shadow, "(Exception)"); - } - } - Printf(f_shadow, ":\n"); - if (have_docstring(n)) { - String *str = docstring(n, AUTODOC_CLASS, tab4); - if (str && Len(str)) - Printv(f_shadow, tab4, str, "\n", NIL); - } - if (!modern) { - Printv(f_shadow, tab4, "__swig_setmethods__ = {}\n", NIL); - if (Len(base_class)) { - Printf(f_shadow, "%sfor _s in [%s]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))\n", tab4, base_class); - } + Printv(f_shadow, "class ", class_name, 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); + if (Len(base_class)) { + Printf(f_shadow, "(%s)", base_class); } else { - Printv(f_shadow, tab4, "__setattr__ = lambda self, name, value: _swig_setattr_nondynamic(self, ", class_name, ", name, value)\n", NIL); + if (!classic) { + Printf(f_shadow, modern ? "(object)" : "(_object)"); + } + if (GetFlag(n, "feature:exceptionclass")) { + Printf(f_shadow, "(Exception)"); + } } - Printv(f_shadow, tab4, "__swig_getmethods__ = {}\n", NIL); - if (Len(base_class)) { - Printf(f_shadow, "%sfor _s in [%s]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))\n", tab4, base_class); + Printf(f_shadow, ":\n"); + if (have_docstring(n)) { + String *str = docstring(n, AUTODOC_CLASS, tab4); + if (str && Len(str)) + Printv(f_shadow, tab4, str, "\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); + if (!modern) { + Printv(f_shadow, tab4, "__swig_setmethods__ = {}\n", NIL); + if (Len(base_class)) { + Printf(f_shadow, "%sfor _s in [%s]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))\n", tab4, base_class); + } + + 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)) { + Printf(f_shadow, "%sfor _s in [%s]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))\n", tab4, base_class); + } + + 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); + } } } } @@ -2924,34 +3688,52 @@ public: /* Emit all of the members */ in_class = 1; + if (builtin) + builtin_pre_decl(n); /* Overide the shadow file so we can capture its methods */ f_shadow = NewString(""); + // Set up type check for director class constructor + Clear(none_comparison); + if (builtin && Swig_directorclass(n)) { + String *p_real_classname = Copy(real_classname); + SwigType_add_pointer(p_real_classname); + String *mangle = SwigType_manglestr(p_real_classname); + String *descriptor = NewStringf("SWIGTYPE%s", mangle); + Printv(none_comparison, "self->ob_type != ((SwigPyClientData*) (", descriptor, ")->clientdata)->pytype", NIL); + Delete(descriptor); + Delete(mangle); + Delete(p_real_classname); + } else { + Printv(none_comparison, "$arg != Py_None", NIL); + } + Language::classHandler(n); + in_class = 0; /* Complete the class */ if (shadow) { /* Generate a class registration function */ - { - String *smartptr = Getattr(n, "feature:smartptr"); // Replace storing a pointer to underlying class with a smart pointer (intended for use with non-intrusive smart pointers) - SwigType *smart = 0; - if (smartptr) { - SwigType *cpt = Swig_cparse_type(smartptr); - if (cpt) { - smart = SwigType_typedef_resolve_all(cpt); - Delete(cpt); - } else { - // TODO: report line number of where the feature comes from - Swig_error(Getfile(n), Getline(n), "Invalid type (%s) in 'smartptr' feature for class %s.\n", smartptr, real_classname); - } + String *smartptr = Getattr(n, "feature:smartptr"); // Replace storing a pointer to underlying class with a smart pointer (intended for use with non-intrusive smart pointers) + SwigType *smart = 0; + if (smartptr) { + SwigType *cpt = Swig_cparse_type(smartptr); + if (cpt) { + smart = SwigType_typedef_resolve_all(cpt); + Delete(cpt); + } else { + // TODO: report line number of where the feature comes from + Swig_error(Getfile(n), Getline(n), "Invalid type (%s) in 'smartptr' feature for class %s.\n", smartptr, real_classname); } - SwigType *ct = Copy(smart ? smart : real_classname); - SwigType_add_pointer(ct); - SwigType *realct = Copy(real_classname); - SwigType_add_pointer(realct); - SwigType_remember(realct); + } + SwigType *ct = Copy(smart ? smart : real_classname); + SwigType_add_pointer(ct); + SwigType *realct = Copy(real_classname); + SwigType_add_pointer(realct); + SwigType_remember(realct); + if (!builtin) { Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL); Printv(f_wrappers, " PyObject *obj;\n", NIL); if (modernargs) { @@ -2968,15 +3750,16 @@ public: " 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); - Delete(smart); Delete(cname); - Delete(ct); - Delete(realct); } + Delete(smart); + Delete(ct); + Delete(realct); if (!have_constructor) { - Printv(f_shadow_file, tab4, "def __init__(self, *args, **kwargs): raise AttributeError(\"", "No constructor defined", - (Getattr(n, "abstract") ? " - class is abstract" : ""), "\")\n", NIL); - } else if (fastinit) { + if (!builtin) + Printv(f_shadow_file, tab4, "def __init__(self, *args, **kwargs): raise AttributeError(\"", "No constructor defined", + (Getattr(n, "abstract") ? " - class is abstract" : ""), "\")\n", NIL); + } else if (fastinit && !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); @@ -2984,7 +3767,7 @@ public: add_method(cname, cname, 0); Delete(cname); } - if (!have_repr) { + if (!have_repr && !builtin) { /* Supply a repr method for this class */ String *rname = SwigType_namestr(real_classname); if (new_repr) { @@ -2995,12 +3778,20 @@ public: Delete(rname); } + if (builtin) + builtin_post_decl(f_builtins, n); + + if (builtin_tp_init) { + Delete(builtin_tp_init); + builtin_tp_init = 0; + } /* Now emit methods */ - Printv(f_shadow_file, f_shadow, NIL); + if (!builtin) + Printv(f_shadow_file, f_shadow, NIL); /* Now the Ptr class */ - if (classptr) { + 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, @@ -3013,21 +3804,30 @@ public: } } - 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); + 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); } - 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); shadow_indent = 0; Printf(f_shadow_file, "%s\n", f_shadow_stubs); Clear(f_shadow_stubs); } + + if (builtin) { + Clear(class_members); + Clear(builtin_getset); + Clear(builtin_methods); + } + classic = oldclassic; modern = oldmodern; @@ -3066,6 +3866,9 @@ public: String *symname = Getattr(n, "sym:name"); int oldshadow; + if (builtin) + Swig_save("builtin_memberfunc", n, "python:argcount", NIL); + /* Create the default member function */ oldshadow = shadow; /* Disable shadowing when wrapping member functions */ if (shadow) @@ -3073,9 +3876,35 @@ public: Language::memberfunctionHandler(n); shadow = oldshadow; + if (builtin && in_class) { + // Can't use checkAttribute(n, "access", "public") because + // "access" attr isn't set on %extend methods + if (!checkAttribute(n, "access", "private") && strncmp(Char(symname), "operator ", 9) && !Getattr(class_members, symname)) { + String *fullname = Swig_name_member(NULL, class_name, symname); + 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(""); + if (check_kwargs(n)) { + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_VARARGS|METH_KEYWORDS, (char*) \"%s\" },\n", symname, wname, ds); + } else if (argcount == 0) { + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_NOARGS, (char*) \"%s\" },\n", symname, wname, ds); + } else if (argcount == 1) { + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_O, (char*) \"%s\" },\n", symname, wname, ds); + } else { + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_VARARGS, (char*) \"%s\" },\n", symname, wname, ds); + } + Delete(fullname); + Delete(wname); + Delete(ds); + } + } + + if (builtin) + Swig_restore(n); + if (!Getattr(n, "sym:nextSibling")) { - if (shadow) { - int allow_kwargs = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0; + if (shadow && !builtin) { int fproxy = fastproxy; if (Strcmp(symname, "__repr__") == 0) { have_repr = 1; @@ -3089,6 +3918,7 @@ public: Delete(pycode); fproxy = 0; } else { + int allow_kwargs = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0; String *parms = make_pyParmList(n, true, false, allow_kwargs); String *callParms = make_pyParmList(n, true, true, allow_kwargs); if (!have_addtofunc(n)) { @@ -3129,13 +3959,50 @@ public: return SWIG_OK; } + /* ------------------------------------------------------------ * staticmemberfunctionHandler() * ------------------------------------------------------------ */ virtual int staticmemberfunctionHandler(Node *n) { String *symname = Getattr(n, "sym:name"); + if (builtin && in_class) { + Swig_save("builtin_memberconstantHandler", n, "pybuiltin:symname", NIL); + Setattr(n, "pybuiltin:symname", symname); + } Language::staticmemberfunctionHandler(n); + if (builtin && in_class) { + Swig_restore(n); + } + + if (builtin && in_class) { + if ((GetFlagAttr(n, "feature:extend") || checkAttribute(n, "access", "public")) + && !Getattr(class_members, symname)) { + String *fullname = Swig_name_member(NULL, class_name, symname); + String *wname = Swig_name_wrapper(fullname); + Setattr(class_members, symname, n); + int funpack = modernargs && 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) + Append(pyflags, "METH_NOARGS"); + else if (funpack && argcount == 1) + Append(pyflags, "METH_O"); + else + Append(pyflags, "METH_VARARGS"); + if (have_docstring(n)) { + String *ds = cdocstring(n, AUTODOC_STATICFUNC); + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, %s, (char*) \"%s\" },\n", symname, wname, pyflags, ds); + Delete(ds); + } else { + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, %s, \"\" },\n", symname, wname, pyflags); + } + Delete(fullname); + Delete(wname); + Delete(pyflags); + } + return SWIG_OK; + } if (Getattr(n, "sym:nextSibling")) { return SWIG_OK; @@ -3232,55 +4099,55 @@ public: } if (!have_constructor && handled_as_init) { - if (Getattr(n, "feature:shadow")) { - String *pycode = pythoncode(Getattr(n, "feature:shadow"), tab4); - String *pyaction = NewStringf("%s.%s", module, Swig_name_construct(NSPACE_TODO, symname)); - Replaceall(pycode, "$action", pyaction); - Delete(pyaction); - Printv(f_shadow, pycode, "\n", NIL); - Delete(pycode); - } else { - String *pass_self = NewString(""); - Node *parent = Swig_methodclass(n); - String *classname = Swig_class_name(parent); - String *rclassname = Swig_class_name(getCurrentClass()); - assert(rclassname); - - - String *parms = make_pyParmList(n, true, false, allow_kwargs); - /* Pass 'self' only if using director */ - String *callParms = make_pyParmList(n, false, true, allow_kwargs); - - if (use_director) { - Insert(callParms, 0, "_self, "); - Printv(pass_self, tab8, NIL); - Printf(pass_self, "if self.__class__ == %s:\n", classname); - //Printv(pass_self, tab8, tab4, "args = (None,) + args\n", tab8, "else:\n", tab8, tab4, "args = (self,) + args\n", NIL); - Printv(pass_self, tab8, tab4, "_self = None\n", tab8, "else:\n", tab8, tab4, "_self = self\n", NIL); - } - - Printv(f_shadow, tab4, "def __init__(", parms, ")", returnTypeAnnotation(n), ": \n", NIL); - if (have_docstring(n)) - Printv(f_shadow, tab8, docstring(n, AUTODOC_CTOR, tab8), "\n", NIL); - if (have_pythonprepend(n)) - Printv(f_shadow, pythoncode(pythonprepend(n), tab8), "\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); + if (!builtin) { + if (Getattr(n, "feature:shadow")) { + String *pycode = pythoncode(Getattr(n, "feature:shadow"), tab4); + String *pyaction = NewStringf("%s.%s", module, Swig_name_construct(NSPACE_TODO, symname)); + Replaceall(pycode, "$action", pyaction); + Delete(pyaction); + Printv(f_shadow, pycode, "\n", NIL); + Delete(pycode); } else { - Printv(f_shadow, - tab8, "this = ", funcCall(Swig_name_construct(NSPACE_TODO, symname), callParms), "\n", - tab8, "try: self.this.append(this)\n", tab8, "except: self.this = this\n", NIL); + String *pass_self = NewString(""); + Node *parent = Swig_methodclass(n); + String *classname = Swig_class_name(parent); + String *rclassname = Swig_class_name(getCurrentClass()); + assert(rclassname); + + String *parms = make_pyParmList(n, true, false, allow_kwargs); + /* Pass 'self' only if using director */ + String *callParms = make_pyParmList(n, false, true, allow_kwargs); + + if (use_director) { + Insert(callParms, 0, "_self, "); + Printv(pass_self, tab8, NIL); + Printf(pass_self, "if self.__class__ == %s:\n", classname); + //Printv(pass_self, tab8, tab4, "args = (None,) + args\n", tab8, "else:\n", tab8, tab4, "args = (self,) + args\n", NIL); + Printv(pass_self, tab8, tab4, "_self = None\n", tab8, "else:\n", tab8, tab4, "_self = self\n", NIL); + } + + Printv(f_shadow, tab4, "def __init__(", parms, ")", returnTypeAnnotation(n), ": \n", NIL); + if (have_docstring(n)) + Printv(f_shadow, tab8, docstring(n, AUTODOC_CTOR, tab8), "\n", NIL); + if (have_pythonprepend(n)) + Printv(f_shadow, pythoncode(pythonprepend(n), tab8), "\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: self.this.append(this)\n", tab8, "except: self.this = this\n", NIL); + } + if (have_pythonappend(n)) + Printv(f_shadow, pythoncode(pythonappend(n), tab8), "\n\n", NIL); + Delete(pass_self); } - if (have_pythonappend(n)) - Printv(f_shadow, pythoncode(pythonappend(n), tab8), "\n\n", NIL); - Delete(pass_self); + have_constructor = 1; } - have_constructor = 1; } 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 = pythoncode(Getattr(n, "feature:shadow"), ""); String *pyaction = NewStringf("%s.%s", module, Swig_name_construct(NSPACE_TODO, symname)); @@ -3297,13 +4164,21 @@ public: Printv(f_shadow_stubs, tab4, docstring(n, AUTODOC_CTOR, tab4), "\n", NIL); if (have_pythonprepend(n)) Printv(f_shadow_stubs, pythoncode(pythonprepend(n), tab4), "\n", NIL); - Printv(f_shadow_stubs, tab4, "val = ", funcCall(Swig_name_construct(NSPACE_TODO, symname), callParms), "\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); #ifdef USE_THISOWN Printv(f_shadow_stubs, tab4, "val.thisown = 1\n", NIL); #endif if (have_pythonappend(n)) Printv(f_shadow_stubs, pythoncode(pythonappend(n), tab4), "\n", NIL); Printv(f_shadow_stubs, tab4, "return val\n", NIL); + Delete(subfunc); } } } @@ -3319,11 +4194,23 @@ public: String *symname = Getattr(n, "sym:name"); int oldshadow = shadow; + if (builtin && in_class) { + Node *cls = Swig_methodclass(n); + if (!Getattr(cls, "feature:python:tp_dealloc")) { + String *dealloc = Swig_name_destroy(NSPACE_TODO, symname); + String *wdealloc = Swig_name_wrapper(dealloc); + Setattr(cls, "feature:python:tp_dealloc", wdealloc); + Delete(wdealloc); + Delete(dealloc); + } + } + if (shadow) shadow = shadow | PYSHADOW_MEMBER; //Setattr(n,"emit:dealloc","1"); Language::destructorHandler(n); shadow = oldshadow; + if (shadow) { if (Getattr(n, "feature:shadow")) { String *pycode = pythoncode(Getattr(n, "feature:shadow"), tab4); @@ -3373,24 +4260,22 @@ public: Language::membervariableHandler(n); shadow = oldshadow; - if (shadow) { + if (shadow && !builtin) { String *mname = Swig_name_member(NSPACE_TODO, class_name, symname); String *setname = Swig_name_set(NSPACE_TODO, mname); String *getname = Swig_name_get(NSPACE_TODO, mname); - if (shadow) { - 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); + int assignable = is_assignable(n); + if (!modern) { + if (assignable) { + Printv(f_shadow, tab4, "__swig_setmethods__[\"", symname, "\"] = ", module, ".", setname, "\n", NIL); } - if (!classic) { - if (!assignable) { - Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = _swig_property(", module, ".", getname, ")\n", NIL); - } else { - Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = _swig_property(", module, ".", getname, ", ", module, ".", setname, ")\n", NIL); - } + Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = ", module, ".", getname, "\n", NIL); + } + if (!classic) { + if (!assignable) { + Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = _swig_property(", module, ".", getname, ")\n", NIL); + } else { + Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = _swig_property(", module, ".", getname, ", ", module, ".", setname, ")\n", NIL); } } Delete(mname); @@ -3406,11 +4291,17 @@ public: * ------------------------------------------------------------ */ virtual int staticmembervariableHandler(Node *n) { + Swig_save("builtin_staticmembervariableHandler", n, "builtin_symname", NIL); Language::staticmembervariableHandler(n); + Swig_restore(n); - if (shadow && !GetFlag(n, "wrappedasconstant")) { - String *symname = Getattr(n, "sym:name"); - if (GetFlag(n, "hasconsttype")) { + if (GetFlag(n, "wrappedasconstant")) + return SWIG_OK; + + String *symname = Getattr(n, "sym:name"); + + if (shadow) { + if (!builtin && GetFlag(n, "hasconsttype")) { String *mname = Swig_name_member(NSPACE_TODO, class_name, symname); Printf(f_shadow_stubs, "%s.%s = %s.%s.%s\n", class_name, symname, module, global_name, mname); Delete(mname); @@ -3432,31 +4323,51 @@ public: DelWrapper(f); int assignable = is_assignable(n); if (assignable) { + int funpack = modernargs && fastunpack; Wrapper *f = NewWrapper(); Printv(f->def, "SWIGINTERN PyObject *", wrapsetname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL); - Wrapper_add_local(f, "value", "PyObject *value"); Wrapper_add_local(f, "res", "int res"); - Append(f->code, "if (!PyArg_ParseTuple(args,(char *)\"O:set\",&value)) return NULL;\n"); - Printv(f->code, "res = ", varsetname, "(value);\n", NIL); + if (!funpack) { + Wrapper_add_local(f, "value", "PyObject *value"); + Append(f->code, "if (!PyArg_ParseTuple(args,(char *)\"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"); Append(f->code, "}\n"); Wrapper_print(f, f_wrappers); - add_method(setname, wrapsetname, 0); + add_method(setname, wrapsetname, 0, 0, funpack, 1, 1); DelWrapper(f); } - if (!modern) { + 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) { + if (!classic && !builtin) { if (!assignable) { Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = _swig_property(", module, ".", getname, ")\n", NIL); } else { Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = _swig_property(", module, ".", getname, ", ", module, ".", setname, ")\n", NIL); } } + String *getter = Getattr(n, "pybuiltin:getter"); + String *setter = Getattr(n, "pybuiltin:setter"); + Hash *h = NULL; + if (getter || setter) { + h = Getattr(builtin_getset, symname); + if (!h) { + h = NewHash(); + Setattr(h, "static", "1"); + Setattr(builtin_getset, symname, h); + } + } + if (getter) + Setattr(h, "getter", getter); + if (setter) + Setattr(h, "setter", setter); + if (h) + Delete(h); Delete(mname); Delete(getname); Delete(wrapgetname); @@ -3475,13 +4386,19 @@ public: virtual int memberconstantHandler(Node *n) { String *symname = Getattr(n, "sym:name"); + if (builtin && in_class) { + Swig_save("builtin_memberconstantHandler", n, "pybuiltin:symname", NIL); + Setattr(n, "pybuiltin:symname", symname); + } int oldshadow = shadow; if (shadow) shadow = shadow | PYSHADOW_MEMBER; Language::memberconstantHandler(n); shadow = oldshadow; - if (shadow) { + if (builtin && in_class) { + Swig_restore(n); + } else if (shadow) { Printv(f_shadow, tab4, symname, " = ", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), "\n", NIL); } return SWIG_OK; @@ -3679,6 +4596,9 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { } } + if (builtin) + Printv(w->code, "PyObject *self = NULL;\n", NIL); + if (ignored_method) { if (!pure_virtual) { if (!is_void) @@ -3800,7 +4720,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { Wrapper_add_localv(w, source, "swig::SwigVar_PyObject", source, "= 0", NIL); Printf(wrap_args, "%s = SWIG_DIRECTOR_CAST(%s);\n", director, nonconst); Printf(wrap_args, "if (!%s) {\n", director); - Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle); + Printf(wrap_args, "%s = SWIG_InternalNewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle); Append(wrap_args, "} else {\n"); Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director); Printf(wrap_args, "Py_INCREF((PyObject *)%s);\n", source); @@ -3809,7 +4729,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { Printv(arglist, source, NIL); } else { Wrapper_add_localv(w, source, "swig::SwigVar_PyObject", source, "= 0", NIL); - Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle); + 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", // source, nonconst, base); Printv(arglist, source, NIL);