Merged the Python 3.0 support branch. The merging progress is not so smooth, so hope this commit won't make anything broken.

This is the (incomplemete) log produced by svnmerge.py:

Merged revisions 10405-10409,10420-10422,10426,10438,10445,10451,10454-10465,10467,10473-10475,10485,10488-10489,10493-10495,10497,10509-10510,10513-10514,10517,10520,10525,10528-10529,10533-10535,10554-10557,10570,10573,10593,10614,10666-10669,10673,10678,10687,10690,10704-10706,10731,10744,10750-10752,10755,10759,10770,10775-10776,10813,10819 via svnmerge from 
https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2008-bhy



git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10834 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Haoyu Bai 2008-09-11 17:18:07 +00:00
parent 761ef2b98f
commit 3d8ddfc442
75 changed files with 1603 additions and 246 deletions

View File

@ -46,7 +46,7 @@
<li><a href="#Python_nn30">Memory management</a>
<li><a href="#Python_nn31">Python 2.2 and classic classes</a>
</ul>
<li><a href="#directors">Cross language polymorphism</a>
<li><a href="#Python_directors">Cross language polymorphism</a>
<ul>
<li><a href="#Python_nn33">Enabling directors</a>
<li><a href="#Python_nn34">Director classes</a>
@ -101,6 +101,12 @@
<li><a href="#Python_nn71">%feature("docstring")</a>
</ul>
<li><a href="#Python_nn72">Python Packages</a>
<li><a href="#Python_python3support">Python 3 Support</a>
<ul>
<li><a href="#Python_nn74">Function annotation</a>
<li><a href="#Python_nn75">Buffer interface</a>
<li><a href="#Python_nn76">Abstract base classes</a>
</ul>
</ul>
</div>
<!-- INDEX -->
@ -113,9 +119,9 @@
<p>
This chapter describes SWIG's support of Python. SWIG is compatible
with most recent Python versions including Python 2.2 as well as older
versions dating back to Python 1.5.2. For the best results, consider using Python
2.0 or newer.
with most recent Python versions including Python 3.0 and Python 2.6,
as well as older versions dating back to Python 2.0. For the best results,
consider using Python 2.3 or newer.
</p>
<p>
@ -2544,7 +2550,7 @@ class itself. In Python-2.1 and earlier, they have to be accessed as a global
function or through an instance (see the earlier section).
</p>
<H2><a name="directors"></a>30.5 Cross language polymorphism</H2>
<H2><a name="Python_directors"></a>30.5 Cross language polymorphism</H2>
<p>
@ -4929,7 +4935,7 @@ with more than one line.
<p>
Using the <tt>package</tt> option of the <tt>%module</tt> directive
allows you to specify what Python package that the module will be
living in when installed.
living in when installed.
</p>
<div class="code">
@ -4950,6 +4956,241 @@ and also in base class declarations, etc. if the package name is
different than its own.
</p>
<H2><a name="Python_python3support"></a>30.12 Python 3 Support</H2>
<p>
SWIG is able to support Python 3.0. The wrapper code generated by
SWIG can be compiled with both Python 2.x or 3.0. Further more, by
passing the <tt>-py3</tt> command line option to SWIG, wrapper code
with some Python 3 specific features can be generated (see below
subsections for details of these features). The <tt>-py3</tt> option also
disables some incompatible features for Python 3, such as
<tt>-classic</tt>.
<p>
There is a list of known-to-be-broken features in Python 3:
</p>
<ul>
<li>No more support for FILE* typemaps, because PyFile_AsFile has been dropped
in Python 3.</li>
<li>The <tt>-apply</tt> command line option is removed and generating
code using apply() is no longer supported.</li>
</ul>
<p>
The following are Python 3.0 new features that are currently supported by
SWIG.
</p>
<H3><a name="Python_nn74"></a>30.12.1 Function annotation</H3>
<p>
The <tt>-py3</tt> option will enable function annotation support. When used
SWIG is able to generate proxy method definitions like
this:
</p>
<div class="code"><pre>
def foo(self, bar : "int" = 0) -&gt; "void" : ...
</pre></div>
<p>
For details of usage of function annotation, see PEP 3107.
</p>
<H3><a name="Python_nn75"></a>30.12.2 Buffer interface</H3>
<p>
Buffer protocols were revised in Python 3. SWIG also gains a series of
new typemaps to support buffer interfaces. These typemap macros are
defined in <tt>pybuffer.i</tt>, which must be included in order to use them.
By using these typemaps, your wrapped function will be able to
accept any Python object that exposes a suitable buffer interface.
</p>
<p>
For example, the <tt>get_path()</tt> function puts the path string
into the memory pointed to by its argument:
</p>
<div class="code"><pre>
void get_path(char *s);
</pre></div>
<p>
Then you can write a typemap like this: (the following example is
applied to both Python 3.0 and 2.6, since the <tt>bytearray</tt> type
is backported to 2.6.
</p>
<div class="code"><pre>
%include &lt;pybuffer.i&gt;
%pybuffer_mutable_string(char *str);
void get_path(char *s);
</pre></div>
<p>
And then on the Python side the wrapped <tt>get_path</tt> could be used in this
way:
</p>
<div class="targetlang"><pre>
&gt;&gt;&gt; p = bytearray(10)
&gt;&gt;&gt; get_path(p)
&gt;&gt;&gt; print(p)
bytearray(b'/Foo/Bar/\x00')
</pre></div>
<p>
The macros defined in <tt>pybuffer.i</tt> are similar to those in
<tt>cstring.i</tt>:
</p>
<p>
<b>%pybuffer_mutable_binary(parm, size_parm)</b>
</p>
<div class="indent">
<p>
The macro can be used to generate a typemap which maps a buffer of an
object to a pointer provided by <tt>parm</tt> and a size argument
provided by <tt>size_parm</tt>. For example:
</p>
<div class="code"><pre>
%pybuffer_mutable_binary(char *str, size_t size);
...
int snprintf(char *str, size_t size, const char *format, ...);
</pre></div>
<p>
In Python:
</p>
<div class="targetlang"><pre>
&gt;&gt;&gt; buf = bytearray(6)
&gt;&gt;&gt; snprintf(buf, "Hello world!")
&gt;&gt;&gt; print(buf)
bytearray(b'Hello\x00')
&gt;&gt;&gt;
</pre></div>
</div>
<p>
<b>%pybuffer_mutable_string(parm)</b>
</p>
<div class="indent">
<p>
This typemap macro requires the buffer to be a zero terminated string,
and maps the pointer of the buffer to <tt>parm</tt>. For example:
</p>
<div class="code"><pre>
%pybuffer_mutable_string(char *str);
...
size_t make_upper(char *str);
</pre></div>
<p>
In Python:
</p>
<div class="targetlang"><pre>
&gt;&gt;&gt; buf = bytearray(b'foo\x00')
&gt;&gt;&gt; make_upper(buf)
&gt;&gt;&gt; print(buf)
bytearray(b'FOO\x00')
&gt;&gt;&gt;
</pre></div>
<p>
Both <tt>%pybuffer_mutable_binary</tt> and <tt>%pybuffer_mutable_string</tt>
require the provided buffer to be mutable, eg. they can accept a
<tt>bytearray</tt> type but can't accept an immutable <tt>byte</tt>
type.
</p>
</div>
<p>
<b>%pybuffer_binary(parm, size_parm)</b>
</p>
<div class="indent">
<p>
This macro maps an object's buffer to a pointer <tt>parm</tt> and a
size <tt>size_parm</tt>. It is similar to
<tt>%pybuffer_mutable_binary</tt>, except the
<tt>%pybuffer_binary</tt> an accept both mutable and immutable
buffers. As a result, the wrapped function should not modify the buffer.
</p>
</div>
<p>
<b>%pybuffer_string(parm)</b>
</p>
<div class="indent">
<p>
This macro maps an object's buffer as a string pointer <tt>parm</tt>.
It is similar to <tt>%pybuffer_mutable_string</tt> but the buffer
could be both mutable and immutable. And your function should not
modify the buffer.
</p>
</div>
<H3><a name="Python_nn76"></a>30.12.3 Abstract base classes</H3>
<p>
By including <tt>pyabc.i</tt> and using the <tt>-py3</tt> command
line option when calling SWIG, the proxy classes of the STL containers
will automatically gain an appropriate abstract base class. For
example, the following SWIG interface:
</p>
<div class="code"><pre>
%include &lt;pyabc.i&gt;
%include &lt;std_map.i&gt;
%include &lt;std_list.i&gt;
namespace std {
%template(Mapii) map&lt;int, int&gt;;
%template(IntList) list&lt;int&gt;;
}
</pre></div>
<p>
will generate a Python proxy class <tt>Mapii</tt> inheriting from
<tt>collections.MutableMap</tt> and a proxy class <tt>IntList</tt>
inheriting from <tt>collections.MutableSequence</tt>.
</p>
<p>
<tt>pyabc.i</tt> also provides a macro <tt>%pythonabc</tt> that could be
used to define an abstract base class for your own C++ class:
</p>
<div class="code"><pre>
%pythonabc(MySet, collections.MutableSet);
</pre></div>
<p>
For details of abstract base class, please see PEP 3119.
</p>
</body>
</html>

View File

@ -1,5 +1,5 @@
TOP = ../../..
SWIG = $(TOP)/../swig
SWIG = $(TOP)/../preinst-swig
SWIGOPT = -I../../Include
SRCS =
TARGET = gifplot
@ -23,3 +23,4 @@ clean::
rm -f *.gif
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -1,5 +1,5 @@
TOP = ../../..
SWIG = $(TOP)/../swig
SWIG = $(TOP)/../preinst-swig
SWIGOPT = -I../../Interface
SRCS =
TARGET = gifplot
@ -23,3 +23,4 @@ clean::
rm -f *.gif
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -1,5 +1,5 @@
TOP = ../../..
SWIG = $(TOP)/../swig
SWIG = $(TOP)/../preinst-swig
SWIGOPT =
SRCS =
TARGET = simple
@ -23,3 +23,4 @@ clean::
rm -f *.gif
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -223,19 +223,39 @@ perl5_clean:
##################################################################
# Make sure these locate your Python installation
PYTHON_INCLUDE= $(DEFS) @PYINCLUDE@
PYTHON_LIB = @PYLIB@
ifeq (,$(PY3))
PYTHON_INCLUDE= $(DEFS) @PYINCLUDE@
PYTHON_LIB = @PYLIB@
PYTHON = @PYTHON@
else
PYTHON_INCLUDE= $(DEFS) @PY3INCLUDE@
PYTHON_LIB = @PY3LIB@
PYTHON = @PYTHON3@
endif
# Extra Python specific dynamic linking options
PYTHON_DLNK = @PYTHONDYNAMICLINKING@
# Extra Python specific linking options
ifeq (,$(PY3))
PYTHON_DLNK = @PYTHONDYNAMICLINKING@
PYTHON_LINK = @PYLINK@
else
PYTHON_DLNK = @PYTHON3DYNAMICLINKING@
PYTHON_LINK = @PY3LINK@
endif
PYTHON_SO = @PYTHON_SO@
# SWIG option for Python
ifeq (,$(PY3))
SWIGPYTHON = $(SWIG) -python
else
SWIGPYTHON = $(SWIG) -python -py3
endif
# ----------------------------------------------------------------
# Build a C dynamically loadable module
# ----------------------------------------------------------------
python: $(SRCS)
$(SWIG) -python $(SWIGOPT) $(INTERFACE)
$(SWIGPYTHON) $(SWIGOPT) $(INTERFACE)
$(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(SRCS) $(INCLUDES) $(PYTHON_INCLUDE)
$(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(PYTHON_DLNK) $(LIBS) -o $(LIBPREFIX)_$(TARGET)$(PYTHON_SO)
@ -244,7 +264,7 @@ python: $(SRCS)
# -----------------------------------------------------------------
python_cpp: $(SRCS)
$(SWIG) -c++ -python $(SWIGOPT) $(INTERFACE)
$(SWIGPYTHON) -c++ $(SWIGOPT) $(INTERFACE)
$(CXX) -c $(CCSHARED) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) $(PYTHON_INCLUDE)
$(CXXSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(PYTHON_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)_$(TARGET)$(PYTHON_SO)
@ -257,18 +277,37 @@ python_cpp: $(SRCS)
#TKINTER = -L/usr/X11R6.3/lib -L/usr/local/compat/lib -ltk4.0 -ltcl7.4 -lX11
TKINTER =
PYTHON_LIBOPTS = @PYLINK@ @LIBS@ $(TKINTER) $(SYSLIBS)
PYTHON_LIBOPTS = $(PYTHON_LINK) @LIBS@ $(TKINTER) $(SYSLIBS)
python_static: $(SRCS)
$(SWIG) -python -lembed.i $(SWIGOPT) $(INTERFACE)
$(SWIGPYTHON) -lembed.i $(SWIGOPT) $(INTERFACE)
$(CC) $(CFLAGS) @LINKFORSHARED@ $(ISRCS) $(SRCS) $(INCLUDES) \
$(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET)
python_static_cpp: $(SRCS)
$(SWIG) -c++ -python -lembed.i $(SWIGOPT) $(INTERFACE)
$(SWIGPYTHON) -c++ -lembed.i $(SWIGOPT) $(INTERFACE)
$(CXX) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) \
$(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET)
# -----------------------------------------------------------------
# Running a Python example
# -----------------------------------------------------------------
ifeq (,$(PY3))
SCRIPT = runme.py
else
SCRIPT = runme3.py
endif
PY2TO3 = 2to3 `2to3 -l | grep -v -E "Available|import$$" | awk '{print "-f "$$0}'`
python_run: $(SCRIPT)
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PYTHONPATH=$(srcdir):$$PYTHONPATH $(PYTHON) $(SCRIPT) >/dev/null
runme3.py: runme.py
cp $< $@
$(PY2TO3) -w $@ >/dev/null 2>&1
# -----------------------------------------------------------------
# Cleaning the python examples
# -----------------------------------------------------------------
@ -278,6 +317,7 @@ python_clean:
rm -f core @EXTRA_CLEAN@
rm -f *.@OBJEXT@ *@SO@ *@PYTHON_SO@
##################################################################
##### OCTAVE ######
##################################################################

View File

@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -18,3 +18,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -21,3 +21,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -18,3 +18,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -18,3 +18,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -19,3 +19,4 @@ clean::
@rm -f foo.py bar.py spam.py base.py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -19,3 +19,4 @@ clean::
@rm -f foo.py bar.py spam.py base.py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,6 +17,7 @@ extern int gcd(int x, int y);
%typemap(in,fragment="t_output_helper") (int argc, char *argv[]) {
int i;
int l;
if (!PyList_Check($input)) {
SWIG_exception(SWIG_ValueError, "Expecting a list");
}
@ -27,11 +28,21 @@ extern int gcd(int x, int y);
$2 = (char **) malloc(($1+1)*sizeof(char *));
for (i = 0; i < $1; i++) {
PyObject *s = PyList_GetItem($input,i);
if (!PyString_Check(s)) {
%#if PY_VERSION_HEX >= 0x03000000
if (!PyUnicode_Check(s))
%#else
if (!PyString_Check(s))
%#endif
{
free($2);
SWIG_exception(SWIG_ValueError, "List items must be strings");
}
%#if PY_VERSION_HEX >= 0x03000000
$2[i] = PyUnicode_AsStringAndSize(s, &l);
%#else
$2[i] = PyString_AsString(s);
%#endif
}
$2[i] = 0;
}
@ -39,12 +50,21 @@ extern int gcd(int x, int y);
extern int gcdmain(int argc, char *argv[]);
%typemap(in) (char *bytes, int len) {
%#if PY_VERSION_HEX >= 0x03000000
if (!PyUnicode_Check($input)) {
PyErr_SetString(PyExc_ValueError,"Expected a string");
return NULL;
}
$1 = PyUnicode_AsStringAndSize($input, &$2);
%#else
if (!PyString_Check($input)) {
PyErr_SetString(PyExc_ValueError,"Expected a string");
return NULL;
}
$1 = PyString_AsString($input);
$2 = PyString_Size($input);
%#endif
}
extern int count(char *bytes, int len, char c);
@ -56,9 +76,15 @@ extern int count(char *bytes, int len, char c);
so that we don't violate it's mutability */
%typemap(in) (char *str, int len) {
%#if PY_VERSION_HEX >= 0x03000000
$2 = PyUnicode_GetSize($input);
$1 = (char *) malloc($2+1);
memmove($1,PyUnicode_AsString($input),$2);
%#else
$2 = PyString_Size($input);
$1 = (char *) malloc($2+1);
memmove($1,PyString_AsString($input),$2);
%#endif
}
/* Return the mutated string as a new object. The t_output_helper
@ -67,7 +93,11 @@ extern int count(char *bytes, int len, char c);
%typemap(argout) (char *str, int len) {
PyObject *o;
%#if PY_VERSION_HEX >= 0x03000000
o = PyUnicode_FromStringAndSize($1,$2);
%#else
o = PyString_FromStringAndSize($1,$2);
%#endif
$result = t_output_helper($result,o);
free($1);
}

View File

@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -18,3 +18,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -22,3 +22,4 @@ run:
python runme.py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -22,3 +22,4 @@ clean::
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -17,3 +17,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -19,3 +19,4 @@ clean::
rm -f $(TARGET).py
check: all
$(MAKE) -f $(TOP)/Makefile python_run

View File

@ -237,6 +237,7 @@ CPP_TEST_CASES += \
null_pointer \
operator_overload \
operator_overload_break \
operbool \
ordering \
overload_copy \
overload_extend \

View File

@ -4,7 +4,7 @@
#ifndef SWIG_CSTRING_UNIMPL
%cstring_input_binary(char *in, int n);
%cstring_input_binary(char *str_in, int n);
%cstring_bounded_output(char *out1, 512);
%cstring_chunk_output(char *out2, 64);
%cstring_bounded_mutable(char *out3, 512);
@ -22,13 +22,13 @@
%inline %{
int count(char *in, int n, char c) {
int count(char *str_in, int n, char c) {
int r = 0;
while (n > 0) {
if (*in == c) {
if (*str_in == c) {
r++;
}
in++;
str_in++;
--n;
}
return r;

View File

@ -4,7 +4,7 @@
#ifndef SWIG_CWSTRING_UNIMPL
%cwstring_input_binary(wchar_t *in, int n);
%cwstring_input_binary(wchar_t *str_in, int n);
%cwstring_bounded_output(wchar_t *out1, 512);
%cwstring_chunk_output(wchar_t *out2, 64);
%cwstring_bounded_mutable(wchar_t *out3, 512);
@ -22,13 +22,13 @@
%inline %{
int count(wchar_t *in, int n, wchar_t c) {
int count(wchar_t *str_in, int n, wchar_t c) {
int r = 0;
while (n > 0) {
if (*in == c) {
if (*str_in == c) {
r++;
}
in++;
str_in++;
--n;
}
return r;

View File

@ -58,13 +58,12 @@ namespace std
%template(max_i) max<int>;
%inline {
/* silently rename the parameter names in csharp/java */
#ifdef SWIGR
double foo(double inparam, double out) { return 1.0; }
#else
double foo(double in, double out) { return 1.0; }
double foo(double abstract, double out) { return 1.0; }
#endif
double bar(double native, bool boolean) { return 1.0; }
}

View File

@ -75,7 +75,7 @@ namespace test {
class string_class;
#ifdef SWIGPYTHON
%typemap(in) string_class * {
$1 = new string_class(PyString_AsString($input));
$1 = new string_class(SWIG_Python_str_AsChar($input));
}
%typemap(freearg) string_class * {
delete $1;

View File

@ -0,0 +1,10 @@
%module operbool
%inline %{
class Test {
public:
operator bool() {
return false;
}
};
%}

View File

@ -2,14 +2,41 @@
# Makefile for python test-suite
#######################################################################
ifeq (,$(PY3))
PYBIN = @PYTHON@
else
PYBIN = @PYTHON3@
endif
LANGUAGE = python
PYTHON = @PYTHON@
SCRIPTSUFFIX = _runme.py
ifneq (,$(USE_VALGRIND))
PYTHON = valgrind --leak-check=full --suppressions=pyswig.supp $(PYBIN)
else
PYTHON = $(PYBIN)
endif
#*_runme.py for Python 2.x, *_runme3.py for Python 3.x
PY2SCRIPTSUFFIX = _runme.py
PY3SCRIPTSUFFIX = _runme3.py
ifeq (,$(PY3))
SCRIPTSUFFIX = $(PY2SCRIPTSUFFIX)
else
SCRIPTSUFFIX = $(PY3SCRIPTSUFFIX)
endif
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
#Use the tricky command because we want to disable the "import" fixer,
#but currently 2to3 has no option to let us do it
PY2TO3 = 2to3 `2to3 -l | grep -v -E "Available|import$$" | awk '{print "-f "$$0}'`
CPP_TEST_CASES += \
abstractbase \
argcargvtest \
autodoc \
callback \
@ -77,12 +104,35 @@ VALGRIND_OPT += --suppressions=pythonswig.supp
+$(swig_and_compile_multi_cpp)
$(run_testcase)
# Call 2to3 to generate Python 3.x test from the Python 2.x's *_runme.py file
%$(PY3SCRIPTSUFFIX): %$(PY2SCRIPTSUFFIX)
cp $< $@
$(PY2TO3) -w $@ >/dev/null 2>&1
# Runs the testcase. A testcase is only run if
# a file is found which has _runme.py appended after the testcase name.
# a file is found which has _runme.py (or _runme3.py for Python 3) appended after the testcase name.
run_python = env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PYTHONPATH=$(srcdir):$$PYTHONPATH $(RUNTOOL) $(PYTHON) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX)
ifeq (,$(PY3))
run_testcase = \
if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PYTHONPATH=$(srcdir):$$PYTHONPATH $(RUNTOOL) $(PYTHON) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \
$(run_python);)\
fi;
else
py2_runme = $(srcdir)/$(SCRIPTPREFIX)$*$(PY2SCRIPTSUFFIX)
py3_runme = $(srcdir)/$(SCRIPTPREFIX)$*$(PY3SCRIPTSUFFIX)
run_testcase = \
if [ -f $(py2_runme) ]; then ( \
$(MAKE) -f $(srcdir)/Makefile $(py3_runme) && \
$(run_python);) \
elif [ -f $(py3_runme)]; then ( \
$(run_python);) \
fi;
endif
# Clean: remove the generated .py file
%.clean:
@ -101,14 +151,15 @@ cvsignore:
@echo clientdata_prop_b.py
@echo imports_a.py
@echo imports_b.py
@echo mod_a.py mod_b.py
@echo mod_a.py mod_b.py
@echo hugemod.h hugemod_a.i hugemod_b.i hugemod_a.py hugemod_b.py hugemod_runme.py
@echo template_typedef_import.py
hugemod_runme = hugemod$(SCRIPTPREFIX)
hugemod:
perl hugemod.pl
perl hugemod.pl $(hugemod_runme)
$(MAKE) hugemod_a.cpptest
$(MAKE) hugemod_b.cpptest
time $(PYTHON) hugemod_runme.py
time $(PYTHON) hugemod_runme.py
sh -c "time $(PYTHON) $(hugemod_runme)"
sh -c "time $(PYTHON) $(hugemod_runme)"

View File

@ -1,4 +1,8 @@
See ../README for common README file.
Any testcases which have _runme.py appended after the testcase name will be detected and run.
Any testcases which have _runme.py (or _runme3.py for Python 3) appended after the testcase name will be detected and run.
If you intend to write a testcase for both Python 2.x and 3.x, do *not* directly put the _runme3.py in this directory. Just write Python 2.x's _runme.py testcase and it will be automatically converted to Python 3 code during test.
You can run make with PY3=y to run test case with Python 3.x, eg.
$ make voidtest.cpptest PY3=y

View File

@ -0,0 +1,18 @@
%module abstractbase
%include <pyabc.i>
%include <std_map.i>
%include <std_multimap.i>
%include <std_set.i>
%include <std_multiset.i>
%include <std_list.i>
%include <std_vector.i>
namespace std
{
%template(Mapii) map<int, int>;
%template(Multimapii) multimap<int, int>;
%template(IntSet) set<int>;
%template(IntMultiset) multiset<int>;
%template(IntVector) vector<int>;
%template(IntList) list<int>;
}

View File

@ -0,0 +1,8 @@
from abstractbase import *
from collections import *
assert issubclass(Mapii, MutableMapping)
assert issubclass(Multimapii, MutableMapping)
assert issubclass(IntSet, MutableSet)
assert issubclass(IntMultiset, MutableSet)
assert issubclass(IntVector, MutableSequence)
assert issubclass(IntList, MutableSequence)

View File

@ -3,20 +3,20 @@ import cpp_namespace
n = cpp_namespace.fact(4)
if n != 24:
raise "Bad return value!"
raise RuntimeError("Bad return value!")
if cpp_namespace.cvar.Foo != 42:
raise "Bad variable value!"
raise RuntimeError("Bad variable value!")
t = cpp_namespace.Test()
if t.method() != "Test::method":
raise "Bad method return value!"
raise RuntimeError("Bad method return value!")
if cpp_namespace.do_method(t) != "Test::method":
raise "Bad return value!"
raise RuntimeError("Bad return value!")
if cpp_namespace.do_method2(t) != "Test::method":
raise "Bad return value!"
raise RuntimeError("Bad return value!")
cpp_namespace.weird("hello", 4)
@ -28,18 +28,18 @@ t4 = cpp_namespace.Test4()
t5 = cpp_namespace.Test5()
if cpp_namespace.foo3(42) != 42:
raise "Bad return value!"
raise RuntimeError("Bad return value!")
if cpp_namespace.do_method3(t2,40) != "Test2::method":
raise "Bad return value!"
raise RuntimeError("Bad return value!")
if cpp_namespace.do_method3(t3,40) != "Test3::method":
raise "Bad return value!"
raise RuntimeError("Bad return value!")
if cpp_namespace.do_method3(t4,40) != "Test4::method":
raise "Bad return value!"
raise RuntimeError("Bad return value!")
if cpp_namespace.do_method3(t5,40) != "Test5::method":
raise "Bad return value!"
raise RuntimeError("Bad return value!")

View File

@ -1,56 +1,56 @@
from director_classic import *
class TargetLangPerson(Person):
def __init__(self):
Person.__init__(self)
def id(self):
identifier = "TargetLangPerson"
return identifier
def __init__(self):
Person.__init__(self)
def id(self):
identifier = "TargetLangPerson"
return identifier
class TargetLangChild(Child):
def __init__(self):
Child.__init__(self)
def id(self):
identifier = "TargetLangChild"
return identifier
def __init__(self):
Child.__init__(self)
def id(self):
identifier = "TargetLangChild"
return identifier
class TargetLangGrandChild(GrandChild):
def __init__(self):
GrandChild.__init__(self)
def id(self):
identifier = "TargetLangGrandChild"
return identifier
def __init__(self):
GrandChild.__init__(self)
def id(self):
identifier = "TargetLangGrandChild"
return identifier
# Semis - don't override id() in target language
class TargetLangSemiPerson(Person):
def __init__(self):
Person.__init__(self)
def __init__(self):
Person.__init__(self)
# No id() override
class TargetLangSemiChild(Child):
def __init__(self):
Child.__init__(self)
def __init__(self):
Child.__init__(self)
# No id() override
class TargetLangSemiGrandChild(GrandChild):
def __init__(self):
GrandChild.__init__(self)
def __init__(self):
GrandChild.__init__(self)
# No id() override
# Orphans - don't override id() in C++
class TargetLangOrphanPerson(OrphanPerson):
def __init__(self):
OrphanPerson.__init__(self)
def id(self):
identifier = "TargetLangOrphanPerson"
return identifier
def __init__(self):
OrphanPerson.__init__(self)
def id(self):
identifier = "TargetLangOrphanPerson"
return identifier
class TargetLangOrphanChild(OrphanChild):
def __init__(self):
Child.__init__(self)
def id(self):
identifier = "TargetLangOrphanChild"
return identifier
def __init__(self):
Child.__init__(self)
def id(self):
identifier = "TargetLangOrphanChild"
return identifier
def check(person, expected):
@ -61,7 +61,7 @@ def check(person, expected):
if (debug):
print(ret)
if (ret != expected):
raise ("Failed. Received: " + ret + " Expected: " + expected)
raise RuntimeError("Failed. Received: " + str(ret) + " Expected: " + expected)
# Polymorphic call from C++
caller = Caller()
@ -70,7 +70,7 @@ def check(person, expected):
if (debug):
print(ret)
if (ret != expected):
raise ("Failed. Received: " + ret + " Expected: " + expected)
raise RuntimeError("Failed. Received: " + str(ret) + " Expected: " + expected)
# Polymorphic call of object created in target language and passed to C++ and back again
baseclass = caller.baseClass()
@ -78,7 +78,7 @@ def check(person, expected):
if (debug):
print(ret)
if (ret != expected):
raise ("Failed. Received: " + ret + " Expected: " + expected)
raise RuntimeError("Failed. Received: " + str(ret)+ " Expected: " + expected)
caller.resetCallback()
if (debug):

View File

@ -1,5 +1,4 @@
from director_exception import *
from exceptions import *
class MyException(Exception):
def __init__(self, a, b):

View File

@ -1,7 +1,8 @@
import sys
import file_test
file_test.nfile(sys.stdout)
if sys.version_info < (3,0):
file_test.nfile(sys.stdout)
cstdout = file_test.GetStdOut()

View File

@ -2,8 +2,12 @@
use strict;
my $modsize = 399; #adjust it so you can have a smaller or bigger hugemod
my $runme = shift @ARGV;
open HEADER, ">hugemod.h" or die "error";
open TEST, ">hugemod_runme.py" or die "error";
open TEST, ">$runme" or die "error";
open I1, ">hugemod_a.i" or die "error";
open I2, ">hugemod_b.i" or die "error";
@ -21,7 +25,7 @@ print I2 "\%inline \%{\n";
my $i;
for ($i = 0; $i < 6000; $i++) {
for ($i = 0; $i < $modsize; $i++) {
my $t = $i * 4;
print HEADER "class type$i { public: int a; };\n";
print I2 "class dtype$i : public type$i { public: int b; };\n";

View File

@ -0,0 +1,4 @@
#!/usr/bin/env python
import operbool
assert not operbool.Test()

View File

@ -0,0 +1,34 @@
%module pybuf
%include<pybuffer.i>
%pybuffer_mutable_binary(char *buf1, int len);
%pybuffer_mutable_string(char *buf2);
%pybuffer_binary(const char *buf3, int len);
%pybuffer_string(const char *buf4);
%inline %{
void func1(char *buf1, int len)
{
int i;
for (i=0; i<len; ++i)
buf1[i] = 'a';
return;
}
void func2(char *buf2)
{
strcpy(buf2, "Hello world!");
}
int func3(const char *buf3, int len)
{
int count = 0;
int i;
for(i=0; i<len; ++i)
if (isalnum(buf3[i]))
++count;
return count;
}
int func4(const char *buf4)
{
return strlen(buf4);
}
%}

View File

@ -0,0 +1,31 @@
%module pybuf_benchmark
%include<pybuffer.i>
%include<cstring.i>
%pybuffer_mutable_string(char *str1);
%cstring_mutable(char *str2);
%inline %{
void title(char *str) {
int outword = 0;
while(*str) {
if (isalnum(*str)) {
if (outword) {
outword = 1;
*str = toupper(*str);
}
}
else {
outword = 0;
}
str++;
}
}
void title1(char *str1) {
title(str1);
}
void title2(char *str2) {
title(str2);
}
%}

View File

@ -0,0 +1,16 @@
import pybuf
import time
k=1000000
n=7
t=time.time()
a = bytearray(b'hello world')
for i in range(k):
pybuf.title1(a)
print "Time used by bytearray:",time.time()-t
t=time.time()
b = 'hello world'
for i in range(k):
pybuf.title2(b)
print "Time used by string:",time.time()-t

View File

@ -0,0 +1,16 @@
import pybuf
import time
k=1000000
n=7
t=time.time()
a = bytearray(b'hello world')
for i in range(k):
pybuf.title1(a)
print("Time used by bytearray:",time.time()-t)
t=time.time()
b = 'hello world'
for i in range(k):
pybuf.title2(b)
print("Time used by string:",time.time()-t)

View File

@ -0,0 +1,15 @@
import pybuf
buf1 = bytearray(10)
buf2 = bytearray(50)
pybuf.func1(buf1)
assert buf1 == b'a'*10
pybuf.func2(buf2)
assert buf2.startswith(b"Hello world!\x00")
count = pybuf.func3(buf2)
assert count==10 #number of alpha and number in 'Hello world!'
length = pybuf.func4(buf2)
assert length==12

View File

@ -1,4 +1,3 @@
import string
from template_typedef_cplx2 import *
#
@ -13,7 +12,7 @@ except:
raise RuntimeError
s = '%s' % d
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print d, "is not an ArithUnaryFunction"
raise RuntimeError
@ -25,7 +24,7 @@ except:
raise RuntimeError
s = '%s' % e
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print e, "is not an ArithUnaryFunction"
raise RuntimeError
@ -42,7 +41,7 @@ except:
raise RuntimeError
s = '%s' % c
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print c, "is not an ArithUnaryFunction"
raise RuntimeError
@ -54,7 +53,7 @@ except:
raise RuntimeError
s = '%s' % f
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print f, "is not an ArithUnaryFunction"
raise RuntimeError
@ -70,7 +69,7 @@ except:
raise RuntimeError
s = '%s' % g
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print g, "is not an ArithUnaryFunction"
raise RuntimeError
@ -83,7 +82,7 @@ except:
raise RuntimeError
s = '%s' % h
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print h, "is not an ArithUnaryFunction"
raise RuntimeError

View File

@ -1,4 +1,3 @@
import string
from template_typedef_cplx import *
#
@ -13,7 +12,7 @@ except:
raise RuntimeError
s = '%s' % d
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print d, "is not an ArithUnaryFunction"
raise RuntimeError
@ -25,7 +24,7 @@ except:
raise RuntimeError
s = '%s' % e
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print e, "is not an ArithUnaryFunction"
raise RuntimeError
@ -42,7 +41,7 @@ except:
raise RuntimeError
s = '%s' % c
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print c, "is not an ArithUnaryFunction"
raise RuntimeError
@ -54,7 +53,7 @@ except:
raise RuntimeError
s = '%s' % f
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print f, "is not an ArithUnaryFunction"
raise RuntimeError
@ -70,7 +69,7 @@ except:
raise RuntimeError
s = '%s' % g
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print g, "is not an ArithUnaryFunction"
raise RuntimeError
@ -83,6 +82,6 @@ except:
raise RuntimeError
s = '%s' % h
if string.find(s, 'ArithUnaryFunction') == -1:
if str.find(s, 'ArithUnaryFunction') == -1:
print h, "is not an ArithUnaryFunction"
raise RuntimeError

View File

@ -20,11 +20,13 @@ SWIG_AsValFilePtr(PyObject *obj, FILE **val) {
if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
if (val) *val = (FILE *)vptr;
return SWIG_OK;
}
}
%#if PY_VERSION_HEX < 0x03000000
if (PyFile_Check(obj)) {
if (val) *val = PyFile_AsFile(obj);
return SWIG_OK;
}
%#endif
return SWIG_TypeError;
}
}

10
Lib/python/pyabc.i Normal file
View File

@ -0,0 +1,10 @@
%define %pythonabc(Type, Abc)
%feature("python:abc", #Abc) Type;
%enddef
%pythoncode {import collections};
%pythonabc(std::vector, collections.MutableSequence);
%pythonabc(std::list, collections.MutableSequence);
%pythonabc(std::map, collections.MutableMapping);
%pythonabc(std::multimap, collections.MutableMapping);
%pythonabc(std::set, collections.MutableSet);
%pythonabc(std::multiset, collections.MutableSet);

View File

@ -27,6 +27,20 @@ typedef struct swig_const_info {
swig_type_info **ptype;
} swig_const_info;
/* -----------------------------------------------------------------------------
* Wrapper of PyInstanceMethod_New() used in Python 3
* It is exported to the generated module, used for -fastproxy
* ----------------------------------------------------------------------------- */
SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
{
#if PY_VERSION_HEX >= 0x03000000
return PyInstanceMethod_New(func);
#else
return NULL;
#endif
}
#ifdef __cplusplus
#if 0
{ /* cc-mode */

107
Lib/python/pybuffer.i Normal file
View File

@ -0,0 +1,107 @@
/* Impelementing buffer protocol typemaps */
/* %pybuffer_mutable_binary(TYPEMAP, SIZE)
*
* Macro for functions accept mutable buffer pointer with a size.
* This can be used for both input and output. For example:
*
* %pybuffer_mutable_binary(char *buff, int size);
* void foo(char *buff, int size) {
* for(int i=0; i<size; ++i)
* buff[i]++;
* }
*/
%define %pybuffer_mutable_binary(TYPEMAP, SIZE)
%typemap(in) (TYPEMAP, SIZE)
(int res, Py_ssize_t size = 0, void *buf = 0) {
res = PyObject_AsWriteBuffer($input, &buf, &size);
if (res<0) {
PyErr_Clear();
%argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
}
$1 = ($1_ltype) buf;
$2 = ($2_ltype) size;
}
%enddef
/* %pybuffer_mutable_string(TYPEMAP, SIZE)
*
* Macro for functions accept mutable zero terminated string pointer.
* This can be used for both input and output. For example:
*
* %pybuffer_mutable_string(char *str);
* void foo(char *str) {
* while(*str) {
* *str = toupper(*str);
* str++;
* }
*/
%define %pybuffer_mutable_string(TYPEMAP)
%typemap(in) (TYPEMAP)
(int res, Py_ssize_t size = 0, void *buf = 0) {
res = PyObject_AsWriteBuffer($input, &buf, &size);
if (res<0) {
PyErr_Clear();
%argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
}
$1 = ($1_ltype) buf;
}
%enddef
/* pybuffer_binary(TYPEMAP, SIZE)
*
* Macro for functions accept read only buffer pointer with a size.
* This must be used for input. For example:
*
* %pybuffer_binary(char *buff, int size);
* int foo(char *buff, int size) {
* int count = 0;
* for(int i=0; i<size; ++i)
* if (0==buff[i]) count++;
* return count;
* }
*/
%define %pybuffer_binary(TYPEMAP, SIZE)
%typemap(in) (TYPEMAP, SIZE)
(int res, Py_ssize_t size = 0, const void *buf = 0) {
res = PyObject_AsReadBuffer($input, &buf, &size);
if (res<0) {
PyErr_Clear();
%argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
}
$1 = ($1_ltype) buf;
$2 = ($2_ltype) size;
}
%enddef
/* %pybuffer_string(TYPEMAP, SIZE)
*
* Macro for functions accept read only zero terminated string pointer.
* This can be used for input. For example:
*
* %pybuffer_string(char *str);
* int foo(char *str) {
* int count = 0;
* while(*str) {
* if (isalnum(*str))
* count++;
* str++;
* }
*/
%define %pybuffer_string(TYPEMAP)
%typemap(in) (TYPEMAP)
(int res, Py_ssize_t size = 0, const void *buf = 0) {
res = PyObject_AsReadBuffer($input, &buf, &size);
if (res<0) {
%argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
}
$1 = ($1_ltype) buf;
}
%enddef

View File

@ -116,6 +116,17 @@ namespace std {
bool res;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
res = PyObject_Compare(v, w) < 0;
/* This may fall into a case of inconsistent
eg. ObjA > ObjX > ObjB
but ObjA < ObjB
*/
if( PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError) )
{
/* Objects can't be compared, this mostly occured in Python 3.0 */
/* Compare their ptr directly for a workaround */
res = (v < w);
PyErr_Clear();
}
SWIG_PYTHON_THREAD_END_BLOCK;
return res;
}
@ -597,6 +608,11 @@ namespace swig
return !(self->empty());
}
/* Alias for Python 3 compatibility */
bool __bool__() const {
return !(self->empty());
}
size_type __len__() const {
return self->size();
}
@ -618,6 +634,14 @@ namespace swig
return x;
}
/* typemap for slice object support */
%typemap(in) PySliceObject* {
$1 = (PySliceObject *) $input;
}
%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) PySliceObject* {
$1 = PySlice_Check($input);
}
Sequence* __getslice__(difference_type i, difference_type j) throw (std::out_of_range) {
return swig::getslice(self, i, j);
}
@ -634,6 +658,43 @@ namespace swig
void __delitem__(difference_type i) throw (std::out_of_range) {
self->erase(swig::getpos(self,i));
}
/* Overloaded methods for Python 3 compatibility
* (Also useful in Python 2.x)
*/
Sequence* __getitem__(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 NULL;
}
PySlice_GetIndices(slice, self->size(), &i, &j, &step);
return swig::getslice(self, i, j);
}
void __setitem__(PySliceObject *slice, const Sequence& v)
throw (std::out_of_range, std::invalid_argument) {
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::setslice(self, i, j, v);
}
void __delitem__(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);
}
}
%enddef

View File

@ -58,12 +58,12 @@ SWIG_Python_AddErrorMsg(const char* mesg)
PyObject *old_str = PyObject_Str(value);
PyErr_Clear();
Py_XINCREF(type);
PyErr_Format(type, "%s %s", PyString_AsString(old_str), mesg);
PyErr_Format(type, "%s %s",
SWIG_Python_str_AsChar(old_str), mesg);
Py_DECREF(old_str);
Py_DECREF(value);
} else {
PyErr_SetString(PyExc_RuntimeError, mesg);
}
}

View File

@ -1,3 +1,47 @@
/* Compatibility marcos for Python 3 */
#if PY_VERSION_HEX >= 0x03000000
#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type)
#define PyInt_Check(x) PyLong_Check(x)
#define PyInt_AsLong(x) PyLong_AsLong(x)
#define PyInt_FromLong(x) PyLong_FromLong(x)
#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args)
#endif
#ifndef Py_TYPE
# define Py_TYPE(op) ((op)->ob_type)
#endif
/* SWIG APIs for compatibility of boht Python 2 & 3 */
#if PY_VERSION_HEX >= 0x03000000
# define SWIG_Python_str_FromFormat PyUnicode_FromFormat
#else
# define SWIG_Python_str_FromFormat PyString_FromFormat
#endif
SWIGINTERN char*
SWIG_Python_str_AsChar(PyObject *str)
{
#if PY_VERSION_HEX >= 0x03000000
str = PyUnicode_AsUTF8String(str);
return PyBytes_AsString(str);
#else
return PyString_AsString(str);
#endif
}
SWIGINTERN PyObject*
SWIG_Python_str_FromChar(const char *c)
{
#if PY_VERSION_HEX >= 0x03000000
return PyUnicode_FromString(c);
#else
return PyString_FromString(c);
#endif
}
/* Add PyOS_snprintf for old Pythons */
#if PY_VERSION_HEX < 0x02020000

View File

@ -33,18 +33,48 @@ typedef struct swig_varlinkobject {
SWIGINTERN PyObject *
swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) {
#if PY_VERSION_HEX >= 0x03000000
return PyUnicode_InternFromString("<Swig global variables>");
#else
return PyString_FromString("<Swig global variables>");
#endif
}
SWIGINTERN PyObject *
swig_varlink_str(swig_varlinkobject *v) {
#if PY_VERSION_HEX >= 0x03000000
PyObject *str = PyUnicode_InternFromString("(");
PyObject *tail;
PyObject *joined;
swig_globalvar *var;
for (var = v->vars; var; var=var->next) {
tail = PyUnicode_FromString(var->name);
joined = PyUnicode_Concat(str, tail);
Py_DecRef(str);
Py_DecRef(tail);
str = joined;
if (var->next) {
tail = PyUnicode_InternFromString(", ");
joined = PyUnicode_Concat(str, tail);
Py_DecRef(str);
Py_DecRef(tail);
str = joined;
}
}
tail = PyUnicode_InternFromString(")");
joined = PyUnicode_Concat(str, tail);
Py_DecRef(str);
Py_DecRef(tail);
str = joined;
#else
PyObject *str = PyString_FromString("(");
swig_globalvar *var;
swig_globalvar *var;
for (var = v->vars; var; var=var->next) {
PyString_ConcatAndDel(&str,PyString_FromString(var->name));
if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", "));
}
PyString_ConcatAndDel(&str,PyString_FromString(")"));
#endif
return str;
}
@ -52,7 +82,7 @@ SWIGINTERN int
swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) {
PyObject *str = swig_varlink_str(v);
fprintf(fp,"Swig global variables ");
fprintf(fp,"%s\n", PyString_AsString(str));
fprintf(fp,"%s\n", SWIG_Python_str_AsChar(str));
Py_DECREF(str);
return 0;
}
@ -110,8 +140,13 @@ swig_varlink_type(void) {
if (!type_init) {
const PyTypeObject tmp
= {
/* PyObject header changed in Python 3 */
#if PY_VERSION_HEX >= 0x03000000
PyVarObject_HEAD_INIT(&PyType_Type, 0)
#else
PyObject_HEAD_INIT(NULL)
0, /* Number of items in variable part (ob_size) */
#endif
(char *)"swigvarlink", /* Type name (tp_name) */
sizeof(swig_varlinkobject), /* Basic size (tp_basicsize) */
0, /* Itemsize (tp_itemsize) */
@ -147,7 +182,10 @@ swig_varlink_type(void) {
#endif
};
varlink_type = tmp;
/* for Python 3 we already assigned the ob_type in PyVarObject_HEAD_INIT() */
#if PY_VERSION_HEX < 0x03000000
varlink_type.ob_type = &PyType_Type;
#endif
type_init = 1;
}
return &varlink_type;
@ -272,13 +310,35 @@ SWIG_Python_FixMethods(PyMethodDef *methods,
#ifdef __cplusplus
extern "C"
#endif
SWIGEXPORT void SWIG_init(void) {
SWIGEXPORT
#if PY_VERSION_HEX >= 0x03000000
PyObject*
#else
void
#endif
SWIG_init(void) {
PyObject *m, *d;
/* Fix SwigMethods to carry the callback ptrs when needed */
SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
#if PY_VERSION_HEX >= 0x03000000
static struct PyModuleDef SWIG_module = {
PyModuleDef_HEAD_INIT,
(char *) SWIG_name,
NULL,
-1,
SwigMethods,
NULL,
NULL,
NULL,
NULL
};
m = PyModule_Create(&SWIG_module);
#else
m = Py_InitModule((char *) SWIG_name, SwigMethods);
#endif
d = PyModule_GetDict(m);
SWIG_InitializeModule(0);

View File

@ -66,6 +66,12 @@ namespace swig {
return obj;
}
/* Make an alias for Python 3.x */
PyObject *__next__()
{
return next();
}
PyObject *previous()
{
SWIG_PYTHON_THREAD_BEGIN_BLOCK; // disable threads
@ -335,6 +341,7 @@ namespace swig
%catches(swig::stop_iteration) PySwigIterator::decr(size_t n = 1);
%catches(std::invalid_argument) PySwigIterator::distance(const PySwigIterator &x) const;
%catches(std::invalid_argument) PySwigIterator::equal (const PySwigIterator &x) const;
%catches(swig::stop_iteration) PySwigIterator::__next__();
%catches(swig::stop_iteration) PySwigIterator::next();
%catches(swig::stop_iteration) PySwigIterator::previous();
%catches(swig::stop_iteration) PySwigIterator::advance(ptrdiff_t n);
@ -370,6 +377,7 @@ namespace swig
virtual PySwigIterator *copy() const = 0;
PyObject *next();
PyObject *__next__();
PyObject *previous();
PySwigIterator *advance(ptrdiff_t n);

View File

@ -33,6 +33,12 @@
/* Special cases */
%rename(__invert__) *::operator~;
%rename(__call__) *::operator();
%feature("shadow") *::operator bool %{
def __nonzero__(self):
return $action(self)
__bool__ = __nonzero__
%};
%rename(__nonzero__) *::operator bool;
/* Ignored operators */

View File

@ -348,9 +348,13 @@ PySwigObject_format(const char* fmt, PySwigObject *v)
PyObject *args = PyTuple_New(1);
if (args) {
if (PyTuple_SetItem(args, 0, PySwigObject_long(v)) == 0) {
PyObject *ofmt = PyString_FromString(fmt);
PyObject *ofmt = SWIG_Python_str_FromChar(fmt);
if (ofmt) {
#if PY_VERSION_HEX >= 0x03000000
res = PyUnicode_Format(ofmt,args);
#else
res = PyString_Format(ofmt,args);
#endif
Py_DECREF(ofmt);
}
Py_DECREF(args);
@ -380,7 +384,7 @@ PySwigObject_repr(PySwigObject *v, PyObject *args)
{
const char *name = SWIG_TypePrettyName(v->ty);
PyObject *hex = PySwigObject_hex(v);
PyObject *repr = PyString_FromFormat("<Swig Object of type '%s' at 0x%s>", name, PyString_AsString(hex));
PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at 0x%U>", name, hex);
Py_DECREF(hex);
if (v->next) {
#ifdef METH_NOARGS
@ -388,7 +392,14 @@ PySwigObject_repr(PySwigObject *v, PyObject *args)
#else
PyObject *nrep = PySwigObject_repr((PySwigObject *)v->next, args);
#endif
#if PY_VERSION_HEX >= 0x03000000
PyObject *joined = PyUnicode_Concat(repr, nrep);
Py_DecRef(repr);
Py_DecRef(nrep);
repr = joined;
#else
PyString_ConcatAndDel(&repr,nrep);
#endif
}
return repr;
}
@ -402,7 +413,7 @@ PySwigObject_print(PySwigObject *v, FILE *fp, int SWIGUNUSEDPARM(flags))
PyObject *repr = PySwigObject_repr(v, NULL);
#endif
if (repr) {
fputs(PyString_AsString(repr), fp);
fputs(SWIG_Python_str_AsChar(repr), fp);
Py_DECREF(repr);
return 0;
} else {
@ -415,7 +426,7 @@ PySwigObject_str(PySwigObject *v)
{
char result[SWIG_BUFFER_SIZE];
return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ?
PyString_FromString(result) : 0;
SWIG_Python_str_FromChar(result) : 0;
}
SWIGRUNTIME int
@ -426,6 +437,24 @@ PySwigObject_compare(PySwigObject *v, PySwigObject *w)
return (i < j) ? -1 : ((i > j) ? 1 : 0);
}
/* Added for Python 3.x, whould it also useful for Python 2.x? */
SWIGRUNTIME PyObject*
PySwigObject_richcompare(PySwigObject *v, PySwigObject *w, int op)
{
PyObject* res;
if( op != Py_EQ && op != Py_NE ) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
if( (PySwigObject_compare(v, w)==0) == (op == Py_EQ) )
res = Py_True;
else
res = Py_False;
Py_INCREF(res);
return res;
}
SWIGRUNTIME PyTypeObject* _PySwigObject_type(void);
SWIGRUNTIME PyTypeObject*
@ -436,8 +465,8 @@ PySwigObject_type(void) {
SWIGRUNTIMEINLINE int
PySwigObject_Check(PyObject *op) {
return ((op)->ob_type == PySwigObject_type())
|| (strcmp((op)->ob_type->tp_name,"PySwigObject") == 0);
return (Py_TYPE(op) == PySwigObject_type())
|| (strcmp(Py_TYPE(op)->tp_name,"PySwigObject") == 0);
}
SWIGRUNTIME PyObject *
@ -610,7 +639,10 @@ _PySwigObject_type(void) {
(binaryfunc)0, /*nb_add*/
(binaryfunc)0, /*nb_subtract*/
(binaryfunc)0, /*nb_multiply*/
/* nb_divide removed in Python 3 */
#if PY_VERSION_HEX < 0x03000000
(binaryfunc)0, /*nb_divide*/
#endif
(binaryfunc)0, /*nb_remainder*/
(binaryfunc)0, /*nb_divmod*/
(ternaryfunc)0,/*nb_power*/
@ -624,13 +656,19 @@ _PySwigObject_type(void) {
0, /*nb_and*/
0, /*nb_xor*/
0, /*nb_or*/
(coercion)0, /*nb_coerce*/
#if PY_VERSION_HEX < 0x03000000
0, /*nb_coerce*/
#endif
(unaryfunc)PySwigObject_long, /*nb_int*/
(unaryfunc)PySwigObject_long, /*nb_long*/
(unaryfunc)0, /*nb_float*/
#if PY_VERSION_HEX < 0x03000000
(unaryfunc)PySwigObject_oct, /*nb_oct*/
(unaryfunc)PySwigObject_hex, /*nb_hex*/
#if PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
#endif
#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */
@ -644,8 +682,13 @@ _PySwigObject_type(void) {
if (!type_init) {
const PyTypeObject tmp
= {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
/* PyOjbect header changed in Python 3 */
#if PY_VERSION_HEX >= 0x03000000
PyVarObject_HEAD_INIT(&PyType_Type, 0)
#else
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
#endif
(char *)"PySwigObject", /* tp_name */
sizeof(PySwigObject), /* tp_basicsize */
0, /* tp_itemsize */
@ -672,7 +715,7 @@ _PySwigObject_type(void) {
swigobject_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
(richcmpfunc)PySwigObject_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
#if PY_VERSION_HEX >= 0x02020000
0, /* tp_iter */
@ -704,7 +747,10 @@ _PySwigObject_type(void) {
#endif
};
pyswigobject_type = tmp;
/* for Python 3 we already assigned the ob_type in PyVarObject_HEAD_INIT() */
#if PY_VERSION_HEX < 0x03000000
pyswigobject_type.ob_type = &PyType_Type;
#endif
type_init = 1;
}
return &pyswigobject_type;
@ -753,9 +799,9 @@ PySwigPacked_repr(PySwigPacked *v)
{
char result[SWIG_BUFFER_SIZE];
if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) {
return PyString_FromFormat("<Swig Packed at %s%s>", result, v->ty->name);
return SWIG_Python_str_FromFormat("<Swig Packed at %s%s>", result, v->ty->name);
} else {
return PyString_FromFormat("<Swig Packed %s>", v->ty->name);
return SWIG_Python_str_FromFormat("<Swig Packed %s>", v->ty->name);
}
}
@ -764,9 +810,9 @@ PySwigPacked_str(PySwigPacked *v)
{
char result[SWIG_BUFFER_SIZE];
if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){
return PyString_FromFormat("%s%s", result, v->ty->name);
return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name);
} else {
return PyString_FromString(v->ty->name);
return SWIG_Python_str_FromChar(v->ty->name);
}
}
@ -811,8 +857,13 @@ _PySwigPacked_type(void) {
if (!type_init) {
const PyTypeObject tmp
= {
/* PyObject header changed in Python 3 */
#if PY_VERSION_HEX>=0x03000000
PyVarObject_HEAD_INIT(&PyType_Type, 0)
#else
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
0, /* ob_size */
#endif
(char *)"PySwigPacked", /* tp_name */
sizeof(PySwigPacked), /* tp_basicsize */
0, /* tp_itemsize */
@ -867,7 +918,10 @@ _PySwigPacked_type(void) {
#endif
};
pyswigpacked_type = tmp;
/* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */
#if PY_VERSION_HEX < 0x03000000
pyswigpacked_type.ob_type = &PyType_Type;
#endif
type_init = 1;
}
return &pyswigpacked_type;
@ -912,7 +966,7 @@ PySwigPacked_UnpackData(PyObject *obj, void *ptr, size_t size)
SWIGRUNTIMEINLINE PyObject *
_SWIG_This(void)
{
return PyString_FromString("this");
return SWIG_Python_str_FromChar("this");
}
SWIGRUNTIME PyObject *
@ -924,6 +978,11 @@ SWIG_This(void)
/* #define SWIG_PYTHON_SLOW_GETSET_THIS */
/* TODO: I don't know how to implement the fast getset in Python 3 right now */
#if PY_VERSION_HEX>=0x03000000
#define SWIG_PYTHON_SLOW_GETSET_THIS
#endif
SWIGRUNTIME PySwigObject *
SWIG_Python_GetSwigThis(PyObject *pyobj)
{
@ -1161,10 +1220,17 @@ SWIG_Python_NewShadowInstance(PySwigClientData *data, PyObject *swig_this)
#endif
}
} else {
#if PY_VERSION_HEX >= 0x03000000
inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
Py_INCREF(data->newargs);
PyObject_SetAttr(inst, SWIG_This(), swig_this);
Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
#else
PyObject *dict = PyDict_New();
PyDict_SetItem(dict, SWIG_This(), swig_this);
inst = PyInstance_NewRaw(data->newargs, dict);
Py_DECREF(dict);
#endif
}
return inst;
#else
@ -1344,8 +1410,13 @@ SWIGRUNTIME void
SWIG_Python_SetModule(swig_module_info *swig_module) {
static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */
#if PY_VERSION_HEX >= 0x03000000
/* Add a dummy module object into sys.modules */
PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
#else
PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
swig_empty_runtime_method_table);
#endif
PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
if (pointer && module) {
PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
@ -1365,7 +1436,7 @@ SWIGRUNTIME swig_type_info *
SWIG_Python_TypeQuery(const char *type)
{
PyObject *cache = SWIG_Python_TypeCache();
PyObject *key = PyString_FromString(type);
PyObject *key = SWIG_Python_str_FromChar(type);
PyObject *obj = PyDict_GetItem(cache, key);
swig_type_info *descriptor;
if (obj) {
@ -1403,9 +1474,9 @@ SWIG_Python_AddErrMesg(const char* mesg, int infront)
Py_XINCREF(type);
PyErr_Clear();
if (infront) {
PyErr_Format(type, "%s %s", mesg, PyString_AsString(old_str));
PyErr_Format(type, "%s %s", mesg, SWIG_Python_str_AsChar(old_str));
} else {
PyErr_Format(type, "%s %s", PyString_AsString(old_str), mesg);
PyErr_Format(type, "%s %s", SWIG_Python_str_AsChar(old_str), mesg);
}
Py_DECREF(old_str);
}
@ -1454,7 +1525,7 @@ SWIG_Python_TypeError(const char *type, PyObject *obj)
const char *otype = (obj ? obj->ob_type->tp_name : 0);
if (otype) {
PyObject *str = PyObject_Str(obj);
const char *cstr = str ? PyString_AsString(str) : 0;
const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0;
if (cstr) {
PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received",
type, otype, cstr);

View File

@ -5,10 +5,20 @@
SWIGINTERN int
SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
{
if (PyString_Check(obj)) {
%#if PY_VERSION_HEX>=0x03000000
if (PyUnicode_Check(obj))
%#else
if (PyString_Check(obj))
%#endif
{
char *cstr; Py_ssize_t len;
%#if PY_VERSION_HEX>=0x03000000
obj = PyUnicode_AsUTF8String(obj);
PyBytes_AsStringAndSize(obj, &cstr, &len);
%#else
PyString_AsStringAndSize(obj, &cstr, &len);
if (cptr) {
%#endif
if (cptr) {
if (alloc) {
/*
In python the user should not be able to modify the inner
@ -33,7 +43,7 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
*alloc = SWIG_OLDOBJ;
}
} else {
*cptr = PyString_AsString(obj);
*cptr = SWIG_Python_str_AsChar(obj);
}
}
if (psize) *psize = len + 1;
@ -64,7 +74,11 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
return pchar_descriptor ?
SWIG_NewPointerObj(%const_cast(carray,char *), pchar_descriptor, 0) : SWIG_Py_Void();
} else {
%#if PY_VERSION_HEX >= 0x03000000
return PyUnicode_FromStringAndSize(carray, %numeric_cast(size,int));
%#else
return PyString_FromStringAndSize(carray, %numeric_cast(size,int));
%#endif
}
} else {
return SWIG_Py_Void();

View File

@ -8,12 +8,14 @@ SWIG_AsWCharPtrAndSize(PyObject *obj, wchar_t **cptr, size_t *psize, int *alloc)
{
PyObject *tmp = 0;
int isunicode = PyUnicode_Check(obj);
%#if PY_VERSION_HEX < 0x03000000
if (!isunicode && PyString_Check(obj)) {
if (cptr) {
obj = tmp = PyUnicode_FromObject(obj);
}
isunicode = 1;
}
%#endif
if (isunicode) {
int len = PyUnicode_GetSize(obj);
if (cptr) {

View File

@ -22,6 +22,10 @@
int res = SWIG_ERROR;
if (PyDict_Check(obj)) {
PyObject_var items = PyObject_CallMethod(obj,(char *)"items",NULL);
%#if PY_VERSION_HEX >= 0x03000000
/* In Python 3.x the ".items()" method return a dict_items object */
items = PySequence_Fast(items, ".items() havn't returned a sequence!");
%#endif
res = traits_asptr_stdseq<std::map<K,T>, std::pair<K, T> >::asptr(items, val);
} else {
map_type *p;

View File

@ -690,7 +690,15 @@ int yylex(void) {
termtoken = SWIG_TOKEN_LPAREN;
termvalue = "(";
break;
} else if (nexttok == SWIG_TOKEN_SEMI) {
} else if (nexttok == SWIG_TOKEN_CODEBLOCK) {
termtoken = SWIG_TOKEN_CODEBLOCK;
termvalue = Scanner_text(scan);
break;
} else if (nexttok == SWIG_TOKEN_LBRACE) {
termtoken = SWIG_TOKEN_LBRACE;
termvalue = "{";
break;
} else if (nexttok == SWIG_TOKEN_SEMI) {
termtoken = SWIG_TOKEN_SEMI;
termvalue = ";";
break;
@ -859,8 +867,14 @@ int yylex(void) {
return (INLINE);
if (strcmp(yytext, "%typemap") == 0)
return (TYPEMAP);
if (strcmp(yytext, "%feature") == 0)
if (strcmp(yytext, "%feature") == 0) {
/* The rename_active indicates we don't need the information of the
* following function's return type. This applied for %rename, so do
* %feature.
*/
rename_active = 1;
return (FEATURE);
}
if (strcmp(yytext, "%except") == 0)
return (EXCEPT);
if (strcmp(yytext, "%importfile") == 0)

View File

@ -2290,21 +2290,25 @@ feature_directive : FEATURE LPAREN idstring RPAREN declarator cpp_const stringbr
String *val = $7 ? NewString($7) : NewString("1");
new_feature($3, val, 0, $5.id, $5.type, $5.parms, $6.qualifier);
$$ = 0;
scanner_clear_rename();
}
| FEATURE LPAREN idstring COMMA stringnum RPAREN declarator cpp_const SEMI {
String *val = Len($5) ? NewString($5) : 0;
new_feature($3, val, 0, $7.id, $7.type, $7.parms, $8.qualifier);
$$ = 0;
scanner_clear_rename();
}
| FEATURE LPAREN idstring featattr RPAREN declarator cpp_const stringbracesemi {
String *val = $8 ? NewString($8) : NewString("1");
new_feature($3, val, $4, $6.id, $6.type, $6.parms, $7.qualifier);
$$ = 0;
scanner_clear_rename();
}
| FEATURE LPAREN idstring COMMA stringnum featattr RPAREN declarator cpp_const SEMI {
String *val = Len($5) ? NewString($5) : 0;
new_feature($3, val, $6, $8.id, $8.type, $8.parms, $9.qualifier);
$$ = 0;
scanner_clear_rename();
}
/* Global feature */
@ -2312,21 +2316,25 @@ feature_directive : FEATURE LPAREN idstring RPAREN declarator cpp_const stringbr
String *val = $5 ? NewString($5) : NewString("1");
new_feature($3, val, 0, 0, 0, 0, 0);
$$ = 0;
scanner_clear_rename();
}
| FEATURE LPAREN idstring COMMA stringnum RPAREN SEMI {
String *val = Len($5) ? NewString($5) : 0;
new_feature($3, val, 0, 0, 0, 0, 0);
$$ = 0;
scanner_clear_rename();
}
| FEATURE LPAREN idstring featattr RPAREN stringbracesemi {
String *val = $6 ? NewString($6) : NewString("1");
new_feature($3, val, $4, 0, 0, 0, 0);
$$ = 0;
scanner_clear_rename();
}
| FEATURE LPAREN idstring COMMA stringnum featattr RPAREN SEMI {
String *val = Len($5) ? NewString($5) : 0;
new_feature($3, val, $6, 0, 0, 0, 0);
$$ = 0;
scanner_clear_rename();
}
;

View File

@ -49,10 +49,11 @@ static String *shadow_indent = 0;
static int in_class = 0;
static int classic = 0;
static int modern = 0;
static int apply = 0;
static int new_repr = 1;
static int no_header_file = 0;
static int py3 = 0;
/* C++ Support + Shadow Classes */
static int have_constructor;
@ -96,7 +97,6 @@ enum autodoc_t {
static const char *usage1 = (char *) "\
Python Options (available with -python)\n\
-aliasobj0 - Alias obj0 when using fastunpack, needed for some old typemaps \n\
-apply - Use apply() in proxy classes\n\
-buildnone - Use Py_BuildValue(" ") to obtain Py_None (default in Windows)\n\
-castmode - Enable the casting mode, which allows implicit cast between types in python\n\
-classic - Use classic classes only\n\
@ -148,6 +148,8 @@ static const char *usage3 = (char *) "\
-O - Enable all the optimization options: \n\
-modern -fastdispatch -dirvtable -nosafecstrings -fvirtual -noproxydel \n\
-fastproxy -fastinit -fastunpack -fastquery -modernargs -nobuildnone \n\
-py3 - Generate code with Python 3 specific features:\n\
Function annotation \n\
\n";
class PYTHON:public Language {
@ -259,9 +261,6 @@ public:
} else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
shadow = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-apply") == 0) {
apply = 1;
Swig_mark_arg(i);
} else if ((strcmp(argv[i], "-new_repr") == 0) || (strcmp(argv[i], "-newrepr") == 0)) {
new_repr = 1;
Swig_mark_arg(i);
@ -284,7 +283,6 @@ public:
} else if (strcmp(argv[i], "-classic") == 0) {
classic = 1;
modernargs = 0;
apply = 1;
modern = 0;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-cppcast") == 0) {
@ -390,7 +388,6 @@ public:
proxydel = 0;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-modern") == 0) {
apply = 0;
classic = 0;
modern = 1;
modernargs = 1;
@ -408,7 +405,6 @@ public:
no_header_file = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-O") == 0) {
apply = 0;
classic = 0;
modern = 1;
dirvtable = 1;
@ -429,8 +425,17 @@ public:
fputs(usage1, stdout);
fputs(usage2, stdout);
fputs(usage3, stdout);
}
} else if (strcmp(argv[i], "-py3") == 0) {
py3 = 1;
Swig_mark_arg(i);
}
}
} /* for */
if (py3) {
/* force disable features that not compatible with Python 3.x */
classic = 0;
}
if (cppcast) {
@ -691,6 +696,13 @@ public:
Printv(f_shadow, "\nfrom sys import version_info\n", NULL);
if(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
@ -719,11 +731,9 @@ public:
* module. */
Printv(f_shadow, "del version_info\n", NULL);
Printv(f_shadow, "import new\n", NULL);
Printv(f_shadow, "new_instancemethod = new.instancemethod\n", NULL);
if (modern || !classic) {
Printv(f_shadow, "try:\n", tab4, "_swig_property = property\n", "except NameError:\n", tab4, "pass # Python < 2.2 doesn't have 'property'.\n", NULL);
}
}
/* if (!modern) */
/* always needed, a class can be forced to be no-modern, such as an exception */
{
@ -750,7 +760,7 @@ public:
"def _swig_getattr(self,class_type,name):\n",
tab4, "if (name == \"thisown\"): return self.this.own()\n",
tab4, "method = class_type.__swig_getmethods__.get(name,None)\n",
tab4, "if method: return method(self)\n", tab4, "raise AttributeError,name\n\n", NIL);
tab4, "if method: return method(self)\n", tab4, "raise AttributeError(name)\n\n", NIL);
Printv(f_shadow,
"def _swig_repr(self):\n",
@ -758,11 +768,17 @@ public:
tab4, "except: strthis = \"\"\n", tab4, "return \"<%s.%s; %s >\" % (self.__class__.__module__, self.__class__.__name__, strthis,)\n\n", NIL);
if (!classic) {
/* Usage of types.ObjectType is deprecated.
* But don't sure wether this would broken old Python?
*/
Printv(f_shadow,
"import types\n",
// "import types\n",
"try:\n",
" _object = types.ObjectType\n",
" _newclass = 1\n", "except AttributeError:\n", " class _object : pass\n", " _newclass = 0\n", "del types\n", "\n\n", NIL);
// " _object = types.ObjectType\n",
" _object = object\n",
" _newclass = 1\n", "except AttributeError:\n", " class _object : pass\n", " _newclass = 0\n",
// "del types\n",
"\n\n", NIL);
}
}
if (modern) {
@ -788,7 +804,11 @@ public:
}
Printf(f_header, "#define SWIG_init init%s\n\n", module);
Printf(f_header, "#if PY_VERSION_HEX >= 0x03000000\n");
Printf(f_header, "# define SWIG_init PyInit_%s\n\n", module);
Printf(f_header, "#else\n");
Printf(f_header, "# define SWIG_init init%s\n\n", module);
Printf(f_header, "#endif\n");
Printf(f_header, "#define SWIG_name \"%s\"\n", module);
Printf(f_wrappers, "#ifdef __cplusplus\n");
@ -797,6 +817,9 @@ public:
Append(const_code, "static swig_const_info swig_const_table[] = {\n");
Append(methods, "static PyMethodDef SwigMethods[] = {\n");
/* the method exported for replacement of new.instancemethod in Python 3 */
add_pyinstancemethod_new();
/* emit code */
Language::top(n);
@ -815,6 +838,12 @@ public:
Append(const_code, "{0, 0, 0, 0.0, 0, 0}};\n");
Printf(f_wrappers, "%s\n", const_code);
initialize_threads(f_init);
Printf(f_init, "#if PY_VERSION_HEX >= 0x03000000\n");
Printf(f_init, " return m;\n");
Printf(f_init, "#else\n");
Printf(f_init, " return;\n");
Printf(f_init, "#endif\n");
Printf(f_init, "}\n");
Printf(f_wrappers, "#ifdef __cplusplus\n");
@ -822,10 +851,6 @@ public:
Printf(f_wrappers, "#endif\n");
if (shadow) {
/*
Printf(f_shadow_imports,"\nimport %s\n", module);
Printv(f_shadow_py, f_shadow_imports, "\n",NIL);
*/
Printv(f_shadow_py, f_shadow, "\n", NIL);
Printv(f_shadow_py, f_shadow_stubs, "\n", NIL);
@ -859,6 +884,19 @@ public:
return SWIG_OK;
}
/* ------------------------------------------------------------
* Emit the wrapper for PyInstanceMethod_New to MethodDef array.
* This wrapper is used to implement -fastproxy,
* as a replacement of new.instancemethod in Python 3.
* ------------------------------------------------------------ */
int add_pyinstancemethod_new()
{
String* name = NewString("SWIG_PyInstanceMethod_New");
Printf(methods, "\t { (char *)\"%s\", (PyCFunction)%s, METH_O, NULL},", name, name);
Delete(name);
return 0;
}
/* ------------------------------------------------------------
* importDirective()
@ -902,25 +940,19 @@ public:
return Language::importDirective(n);
}
/* ------------------------------------------------------------
* emitFuncCallHelper()
* Write the shadow code to call a function in the extension
* module. Takes into account the -apply flag and whether
* to use keyword args or not.
* funcCall()
* Emit shadow code to call a function in the extension
* module. Using proper argument and calling style for
* given node n.
* ------------------------------------------------------------ */
String *funcCall(String *name, String *parms) {
String *str = NewString("");
String *funcCallHelper(String *name, int kw) {
String *str;
str = NewString("");
if (apply) {
Printv(str, "apply(", module, ".", name, ", args", (kw ? ", kwargs" : ""), ")", NIL);
} else {
Printv(str, module, ".", name, "(*args", (kw ? ", **kwargs" : ""), ")", NIL);
}
Printv(str, module, ".", name, "(", parms, ")", NIL);
return str;
}
}
/* ------------------------------------------------------------
* pythoncode() - Output python code into the shadow file
@ -1088,29 +1120,84 @@ public:
return doc;
}
/* -----------------------------------------------------------------------------
* makeParameterName()
* Note: the generated name should consist with that in kwnames[]
*
* Inputs:
* n - Node
* p - parameter node
* arg_num - parameter argument number
* Return:
* arg - a unique parameter name
* ----------------------------------------------------------------------------- */
String *makeParameterName(ParmList *plist, Parm *p, int arg_num) {
String *arg = 0;
String *pn = Swig_name_make(p, 0, Getattr(p, "name"), 0, 0);
// Use C parameter name unless it is a duplicate or an empty parameter name
int count = 0;
if ( SwigType_isvarargs(Getattr(p, "type")) ) {
return NewString("*args");
}
while (plist) {
if ((Cmp(pn, Getattr(plist, "name")) == 0))
count++;
plist = nextSibling(plist);
}
arg = (!pn || !Len(pn) || (count > 1)) ? NewStringf("arg%d", arg_num) : Copy(pn);
return arg;
}
/* ------------------------------------------------------------
* make_autodocParmList()
* Generate the documentation for the function parameters
* Parameters:
* func_annotation: Function annotation support
* ------------------------------------------------------------ */
String *make_autodocParmList(Node *n, bool showTypes) {
String *make_autodocParmList(Node *n, bool showTypes, bool calling=false, bool func_annotation=false) {
String *doc = NewString("");
String *pdocs = Copy(Getattr(n, "feature:pdocs"));
ParmList *plist = CopyParmList(Getattr(n, "parms"));
Parm *p;
Parm *pnext;
Node *lookup;
Node *lookup;
int lines = 0;
int arg_num = 0;
const int maxwidth = 50;
if(calling)
func_annotation = false;
if (pdocs)
Append(pdocs, "\n");
Swig_typemap_attach_parms("in", plist, 0);
Swig_typemap_attach_parms("doc", plist, 0);
if (Strcmp(ParmList_protostr(plist), "void")==0) {
//No parameters actually
return doc;
}
for (p = plist; p; p = pnext) {
String *tm = Getattr(p, "tmap:in");
if (tm) {
pnext = Getattr(p, "tmap:in:next");
if (checkAttribute(p, "tmap:in:numinputs", "0")) {
continue;
}
} else {
pnext = nextSibling(p);
}
String *name = 0;
String *type = 0;
String *value = 0;
@ -1127,12 +1214,14 @@ public:
type = type ? type : Getattr(p, "type");
value = value ? value : Getattr(p, "value");
String *tm = Getattr(p, "tmap:in");
if (tm) {
pnext = Getattr(p, "tmap:in:next");
} else {
pnext = nextSibling(p);
}
name = makeParameterName(plist, p, arg_num);
// Reset it for convinient in further use. (mainly for makeParameterName())
// Since the plist is created by CopyParmList,
// we can hope that the set would have no side effect
Setattr(p, "name", name);
arg_num++;
if (Len(doc)) {
// add a comma to the previous one if any
@ -1144,39 +1233,40 @@ public:
lines += 1;
}
}
type = SwigType_base(type);
lookup = Swig_symbol_clookup(type, 0);
if (lookup)
type = Getattr(lookup, "sym:name");
// Do the param type too?
if (showTypes) {
type = SwigType_base(type);
lookup = Swig_symbol_clookup(type, 0);
if (lookup)
type = Getattr(lookup, "sym:name");
Printf(doc, "%s ", type);
if (showTypes)
Printf(doc, "%s ", type);
Append(doc, name);
if (pdoc) {
if (!pdocs)
pdocs = NewString("Parameters:\n");
Printf(pdocs, " %s\n", pdoc);
}
if (name) {
Append(doc, name);
if (pdoc) {
if (!pdocs)
pdocs = NewString("Parameters:\n");
Printf(pdocs, " %s\n", pdoc);
}
} else {
Append(doc, "?");
}
// Write the function annoation
if (func_annotation)
Printf(doc, " : '%s'", type);
if (value) {
if (Strcmp(value, "NULL") == 0)
value = NewString("None");
else if (Strcmp(value, "true") == 0 || Strcmp(value, "TRUE") == 0)
value = NewString("True");
else if (Strcmp(value, "false") == 0 || Strcmp(value, "FALSE") == 0)
value = NewString("False");
// Write default value
if (value && !calling) {
String* pv = pyvalue(value, Getattr(p, "type"));
if (pv)
value = pv;
else {
lookup = Swig_symbol_clookup(value, 0);
if (lookup)
if (lookup) {
value = Getattr(lookup, "sym:name");
}
}
Printf(doc, "=%s", value);
Printf(doc, " = %s", value);
}
}
if (pdocs)
@ -1314,6 +1404,132 @@ public:
return doc;
}
/* ------------------------------------------------------------
* pyvalue()
* Check if string v can be a Python value literal,
* (eg. number or string), or translate it to a Python literal.
* ------------------------------------------------------------ */
String* pyvalue(String *v, SwigType *t)
{
if (v && Len(v)>0) {
char fc = (Char(v))[0];
if (('0'<=fc && fc<='9') || '\''==fc || '"'==fc) {
/* number or string (or maybe NULL pointer)*/
if (SwigType_ispointer(t) && Strcmp(v, "0")==0)
return NewString("None");
else
return v;
}
if (Strcmp(v, "true")==0 || Strcmp(v, "FALSE")==0)
return NewString("True");
if (Strcmp(v, "false")==0 || Strcmp(v, "FALSE")==0)
return NewString("False");
if (Strcmp(v, "NULL")==0)
return NewString("None");
}
return 0;
}
/* ------------------------------------------------------------
* is_primitive_defaultargs()
* Check if all the default args have primitive type.
* (So we can generate proper parameter list with default
* values..)
* ------------------------------------------------------------ */
bool is_primitive_defaultargs(Node *n)
{
ParmList *plist = CopyParmList(Getattr(n, "parms"));
Parm *p;
Parm *pnext;
Swig_typemap_attach_parms("in", plist, 0);
for (p = plist; p; p = pnext) {
String *tm = Getattr(p, "tmap:in");
if (tm) {
pnext = Getattr(p, "tmap:in:next");
if (checkAttribute(p, "tmap:in:numinputs", "0")) {
continue;
}
} else {
pnext = nextSibling(p);
}
String *type = Getattr(p, "type");
String *value = Getattr(p, "value");
if (!pyvalue(value, type))
return false;
}
return true;
}
/* ------------------------------------------------------------
* is_real_overloaded()
* Check if the function is overloaded, but not just have some
* siblings generated due to the original function have
* default arguments.
* ------------------------------------------------------------ */
bool is_real_overloaded(Node *n)
{
Node *h = Getattr(n, "sym:overloaded");
Node *i;
if (!h)
return false;
i = Getattr(h, "sym:nextSibling");
while (i) {
Node *nn = Getattr(i, "defaultargs");
if (nn != h) {
/* Check if overloaded function has defaultargs and
* pointed to the first overloaded. */
return true;
}
i = Getattr(i, "sym:nextSibling");
}
return false;
}
/* ------------------------------------------------------------
* make_pyParmList()
* Generate parameter list for Python functions or methods,
* reuse make_autodocParmList() to do so.
* ------------------------------------------------------------ */
String* make_pyParmList(Node *n, bool in_class, bool is_calling, int kw)
{
/* Get the original function for a defaultargs copy,
* see default_arguments() in parser.y. */
Node *nn = Getattr(n, "defaultargs");
if (nn) n = nn;
/* For overloaded function, just use *args */
if (is_real_overloaded(n) ||
GetFlag(n, "feature:compactdefaultargs") ||
!is_primitive_defaultargs(n))
{
String *parms = NewString("");
if(in_class)
Printf(parms, "self, ");
Printf(parms, "*args");
if (kw)
Printf(parms, ", **kwargs");
return parms;
}
bool funcanno = py3 ? true : false;
String *params = NewString("");
String *_params = make_autodocParmList(n, false, is_calling, funcanno);
if (in_class)
{
Printf(params, "self");
if(Len(_params) > 0)
Printf(params, ", ");
}
Printv(params, _params, NULL);
return params;
}
/* ------------------------------------------------------------
* have_pythonprepend()
@ -1379,6 +1595,40 @@ public:
return have_pythonappend(n) || have_pythonprepend(n) || have_docstring(n);
}
/* ------------------------------------------------------------
* returnTypeAnnotation()
* Helper function for constructing the function annotation
* of the returning type, return a empty string for Python 2.x
* ------------------------------------------------------------ */
String* returnTypeAnnotation(Node *n)
{
String *ret=0;
Parm *p = Getattr(n, "parms");
String *tm;
/* Try to guess the returning type by argout typemap,
* however the result may not accurate. */
while (p) {
if ((tm=Getattr(p, "tmap:argout:match_type"))) {
tm = SwigType_str(tm, 0);
if (ret)
Printv(ret, ", ", tm, NULL);
else
ret = tm;
p = Getattr(p, "tmap:argout:next");
} else {
p = nextSibling(p);
}
}
/* If no argout typemap, then get the returning type from
* the function prototype. */
if (!ret) {
ret = Getattr(n, "type");
if (ret) ret = SwigType_str(ret, 0);
}
return (ret && py3) ? NewStringf(" -> \"%s\" ", ret)
: NewString("");
}
/* ------------------------------------------------------------
* emitFunctionShadowHelper()
@ -1388,24 +1638,26 @@ public:
* ------------------------------------------------------------ */
void emitFunctionShadowHelper(Node *n, File *f_dest, String *name, int kw) {
if (Getattr(n, "feature:python:callback") || !have_addtofunc(n)) {
/* If there is no addtofunc directive then just assign from the extension module */
Printv(f_dest, name, " = ", module, ".", name, "\n", NIL);
String *parms = make_pyParmList(n, false, false, kw);
String *callParms = make_pyParmList(n, false, true, kw);
/* Make a wrapper function to insert the code into */
Printv(f_dest, "\ndef ", name, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
if (have_docstring(n))
Printv(f_dest, ctab4, docstring(n, AUTODOC_FUNC, tab4), "\n", NIL);
if (have_pythonprepend(n))
Printv(f_dest, ctab4, pythonprepend(n), "\n", NIL);
if (have_pythonappend(n)) {
Printv(f_dest, ctab4, "val = ", funcCall(name, callParms), "\n", NIL);
Printv(f_dest, ctab4, pythonappend(n), "\n", NIL);
Printv(f_dest, ctab4, "return val\n", NIL);
} else {
/* Otherwise make a wrapper function to insert the code into */
Printv(f_dest, "\ndef ", name, "(*args", (kw ? ", **kwargs" : ""), "):\n", NIL);
if (have_docstring(n))
Printv(f_dest, ctab4, docstring(n, AUTODOC_FUNC, tab4), "\n", NIL);
if (have_pythonprepend(n))
Printv(f_dest, ctab4, pythonprepend(n), "\n", NIL);
if (have_pythonappend(n)) {
Printv(f_dest, ctab4, "val = ", funcCallHelper(name, kw), "\n", NIL);
Printv(f_dest, ctab4, pythonappend(n), "\n", NIL);
Printv(f_dest, ctab4, "return val\n", NIL);
} else {
Printv(f_dest, ctab4, "return ", funcCallHelper(name, kw), "\n", NIL);
}
Printv(f_dest, ctab4, "return ", funcCall(name, callParms), "\n", NIL);
}
if (Getattr(n, "feature:python:callback") || !have_addtofunc(n)) {
/* If there is no addtofunc directive then just assign from the extension module (for speed up) */
Printv(f_dest, name, " = ", module, ".", name, "\n", NIL);
}
}
@ -2488,7 +2740,7 @@ public:
Printf(f_directors_h, " PyObject *swig_get_method(size_t method_index, const char *method_name) const {\n");
Printf(f_directors_h, " PyObject *method = vtable[method_index];\n");
Printf(f_directors_h, " if (!method) {\n");
Printf(f_directors_h, " swig::PyObject_var name = PyString_FromString(method_name);\n");
Printf(f_directors_h, " swig::PyObject_var name = SWIG_Python_str_FromChar(method_name);\n");
Printf(f_directors_h, " method = PyObject_GetAttr(swig_get_self(), name);\n");
Printf(f_directors_h, " if (method == NULL) {\n");
Printf(f_directors_h, " std::string msg = \"Method in class %s doesn't exist, undefined \";\n", classname);
@ -2623,6 +2875,16 @@ public:
}
}
}
/* dealing with abstract base class */
String *abcs = Getattr(n, "feature:python:abc");
if (py3 && abcs) {
if (Len(base_class)) {
Putc(',', base_class);
}
Printv(base_class, abcs, NIL);
}
Printv(f_shadow, "class ", class_name, NIL);
if (Len(base_class)) {
@ -2631,6 +2893,9 @@ public:
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)) {
@ -2721,7 +2986,7 @@ public:
Delete(realct);
}
if (!have_constructor) {
Printv(f_shadow_file, tab4, "def __init__(self, *args, **kwargs): raise AttributeError, \"No constructor defined\"\n", NIL);
Printv(f_shadow_file, tab4, "def __init__(self, *args, **kwargs): raise AttributeError(\"No constructor defined\")\n", NIL);
} else if (fastinit) {
Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL);
@ -2834,13 +3099,15 @@ public:
Delete(pycode);
fproxy = 0;
} else {
String *parms = make_pyParmList(n, true, false, allow_kwargs);
String *callParms = make_pyParmList(n, true, true, allow_kwargs);
if (!have_addtofunc(n)) {
if (!fastproxy || olddefs) {
Printv(f_shadow, tab4, "def ", symname, "(*args", (allow_kwargs ? ", **kwargs" : ""), "):", NIL);
Printv(f_shadow, " return ", funcCallHelper(Swig_name_member(class_name, symname), allow_kwargs), "\n", NIL);
Printv(f_shadow, tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":", NIL);
Printv(f_shadow, " return ", funcCall(Swig_name_member(class_name, symname), callParms), "\n", NIL);
}
} else {
Printv(f_shadow, tab4, "def ", symname, "(*args", (allow_kwargs ? ", **kwargs" : ""), "):", NIL);
Printv(f_shadow, tab4, "def ", symname, "(",parms , ")", returnTypeAnnotation(n), ":", NIL);
Printv(f_shadow, "\n", NIL);
if (have_docstring(n))
Printv(f_shadow, tab8, docstring(n, AUTODOC_METHOD, tab8), "\n", NIL);
@ -2850,11 +3117,11 @@ public:
}
if (have_pythonappend(n)) {
fproxy = 0;
Printv(f_shadow, tab8, "val = ", funcCallHelper(Swig_name_member(class_name, symname), allow_kwargs), "\n", NIL);
Printv(f_shadow, tab8, "val = ", funcCall(Swig_name_member(class_name, symname), callParms), "\n", NIL);
Printv(f_shadow, tab8, pythonappend(n), "\n", NIL);
Printv(f_shadow, tab8, "return val\n\n", NIL);
} else {
Printv(f_shadow, tab8, "return ", funcCallHelper(Swig_name_member(class_name, symname), allow_kwargs), "\n\n", NIL);
Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(class_name, symname), callParms), "\n\n", NIL);
}
}
}
@ -2887,17 +3154,19 @@ public:
if (shadow) {
if (!classic && !Getattr(n, "feature:python:callback") && have_addtofunc(n)) {
int kw = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0;
Printv(f_shadow, tab4, "def ", symname, "(*args", (kw ? ", **kwargs" : ""), "):\n", NIL);
String *parms = make_pyParmList(n, true, false, kw);
String *callParms = make_pyParmList(n, true, true, kw);
Printv(f_shadow, tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
if (have_docstring(n))
Printv(f_shadow, tab8, docstring(n, AUTODOC_STATICFUNC, tab8), "\n", NIL);
if (have_pythonprepend(n))
Printv(f_shadow, tab8, pythonprepend(n), "\n", NIL);
if (have_pythonappend(n)) {
Printv(f_shadow, tab8, "val = ", funcCallHelper(Swig_name_member(class_name, symname), kw), "\n", NIL);
Printv(f_shadow, tab8, "val = ", funcCall(Swig_name_member(class_name, symname), callParms), "\n", NIL);
Printv(f_shadow, tab8, pythonappend(n), "\n", NIL);
Printv(f_shadow, tab8, "return val\n\n", NIL);
} else {
Printv(f_shadow, tab8, "return ", funcCallHelper(Swig_name_member(class_name, symname), kw), "\n\n", NIL);
Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(class_name, symname), callParms), "\n\n", NIL);
}
Printv(f_shadow, tab4, modern ? "" : "if _newclass:", symname, " = staticmethod(", symname, ")\n", NIL);
@ -2969,8 +3238,8 @@ public:
handled_as_init = (Strcmp(nname, sname) == 0) || (Strcmp(nname, cname) == 0);
Delete(cname);
}
if (!have_constructor && handled_as_init) {
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(symname));
@ -2984,23 +3253,30 @@ public:
String *classname = Swig_class_name(parent);
String *rclassname = Swig_class_name(getCurrentClass());
assert(rclassname);
if (use_director) {
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, "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__(self, *args", (allow_kwargs ? ", **kwargs" : ""), "): \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, tab8, pythonprepend(n), "\n", NIL);
Printv(f_shadow, pass_self, NIL);
if (fastinit) {
Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self,", funcCallHelper(Swig_name_construct(symname), allow_kwargs), ")\n", NIL);
Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self,", funcCall(Swig_name_construct(symname), callParms), ")\n", NIL);
} else {
Printv(f_shadow,
tab8, "this = ", funcCallHelper(Swig_name_construct(symname), allow_kwargs), "\n",
tab8, "this = ", funcCall(Swig_name_construct(symname), callParms), "\n",
tab8, "try: self.this.append(this)\n", tab8, "except: self.this = this\n", NIL);
}
if (have_pythonappend(n))
@ -3020,13 +3296,15 @@ public:
Printv(f_shadow_stubs, pycode, "\n", NIL);
Delete(pycode);
} else {
String *parms = make_pyParmList(n, true, false, allow_kwargs);
String *callParms = make_pyParmList(n, true, true, allow_kwargs);
Printv(f_shadow_stubs, "\ndef ", symname, "(*args", (allow_kwargs ? ", **kwargs" : ""), "):\n", NIL);
Printv(f_shadow_stubs, "\ndef ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
if (have_docstring(n))
Printv(f_shadow_stubs, tab4, docstring(n, AUTODOC_CTOR, tab4), "\n", NIL);
if (have_pythonprepend(n))
Printv(f_shadow_stubs, tab4, pythonprepend(n), "\n", NIL);
Printv(f_shadow_stubs, tab4, "val = ", funcCallHelper(Swig_name_construct(symname), allow_kwargs), "\n", NIL);
Printv(f_shadow_stubs, tab4, "val = ", funcCall(Swig_name_construct(symname), callParms), "\n", NIL);
#ifdef USE_THISOWN
Printv(f_shadow_stubs, tab4, "val.thisown = 1\n", NIL);
#endif
@ -3605,15 +3883,15 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
if (use_parse || !modernargs) {
Printf(w->code, "swig::PyObject_var result = PyObject_CallMethod(swig_get_self(), (char *)\"%s\", (char *)\"(%s)\" %s);\n",
pyname, parse_args, arglist);
} else {
Printf(w->code, "swig::PyObject_var swig_method_name = PyString_FromString((char *)\"%s\");\n", pyname);
} else {
Printf(w->code, "swig::PyObject_var swig_method_name = SWIG_Python_str_FromChar((char *)\"%s\");\n", pyname);
Printf(w->code, "swig::PyObject_var result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name %s, NULL);\n", arglist);
}
} else {
if (!modernargs) {
Printf(w->code, "swig::PyObject_var result = PyObject_CallMethod(swig_get_self(), (char *) \"%s\", NULL);\n", pyname);
} else {
Printf(w->code, "swig::PyObject_var swig_method_name = PyString_FromString((char *)\"%s\");\n", pyname);
Printf(w->code, "swig::PyObject_var swig_method_name = SWIG_Python_str_FromChar((char *)\"%s\");\n", pyname);
Append(w->code, "swig::PyObject_var result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);\n");
}
}

View File

@ -573,7 +573,7 @@ else
# First figure out the name of the Python executable
if test "x$PYBIN" = xyes; then
AC_CHECK_PROGS(PYTHON, python python2.8 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 python1.6 python1.5 python1.4 python)
AC_CHECK_PROGS(PYTHON, [python python2.8 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 python1.6 python1.5 python1.4 python])
else
PYTHON="$PYBIN"
fi
@ -657,6 +657,103 @@ AC_SUBST(PYLIB)
AC_SUBST(PYLINK)
AC_SUBST(PYTHONDYNAMICLINKING)
#----------------------------------------------------------------
# Look for Python 3.x
#----------------------------------------------------------------
# mostly copy & pasted from "Look for Python" section,
# did some trim, fix and rename
PY3INCLUDE=
PY3LIB=
PY3PACKAGE=
AC_ARG_WITH(python3, AS_HELP_STRING([--without-python3], [Disable Python 3.x support])
AS_HELP_STRING([--with-python3=path], [Set location of Python 3.x executable]),[ PY3BIN="$withval"], [PY3BIN=yes])
# First, check for "--without-python3" or "--with-python3=no".
if test x"${PY3BIN}" = xno -o x"${with_alllang}" = xno ; then
AC_MSG_NOTICE([Disabling Python 3.x support])
else
# First figure out the name of the Python3 executable
if test "x$PY3BIN" = xyes; then
AC_CHECK_PROGS(PYTHON3, [python3 python3.0])
else
PYTHON3="$PY3BIN"
fi
# Check for Python 3.x development tools (header files, static library and python3-config)
AC_CHECK_PROGS(PY3CONFIG, [$PYTHON3-config python3-config python3.0-config])
if test -n "$PYTHON3" -a -n "$PY3CONFIG"; then
AC_MSG_CHECKING([for Python 3.x prefix])
PY3PREFIX=`($PY3CONFIG --prefix) 2>/dev/null`
AC_MSG_RESULT($PY3PREFIX)
AC_MSG_CHECKING(for Python 3.x exec-prefix)
PY3EPREFIX=`($PY3CONFIG --exec-prefix) 2>/dev/null`
AC_MSG_RESULT($PY3EPREFIX)
# Note: I could not think of a standard way to get the version string from different versions.
# This trick pulls it out of the file location for a standard library file.
AC_MSG_CHECKING([for Python 3.x version])
# Need to do this hack since autoconf replaces __file__ with the name of the configure file
filehack="file__"
PY3VERSION=`($PYTHON3 -c "import string,operator,os.path; print(operator.getitem(os.path.split(operator.getitem(os.path.split(string.__$filehack),0)),1))")`
AC_MSG_RESULT($PY3VERSION)
# Find the directory for libraries this is necessary to deal with
# platforms that can have apps built for multiple archs: e.g. x86_64
AC_MSG_CHECKING([for Python 3.x lib dir])
PY3LIBDIR=`($PYTHON3 -c "import sys; print(sys.lib)") 2>/dev/null`
if test -z "$PY3LIBDIR"; then
# some dists don't have sys.lib so the best we can do is assume lib
PY3LIBDIR="lib"
fi
AC_MSG_RESULT($PY3LIBDIR)
# Set the include directory
AC_MSG_CHECKING([for Python 3.x header files])
PY3INCLUDE=`($PY3CONFIG --includes) 2>/dev/null`
AC_MSG_RESULT($PY3INCLUDE)
# Set the library directory blindly. This probably won't work with older versions
AC_MSG_CHECKING([for Python 3.x library])
dirs="$PY3VERSION/config $PY3VERSION/$PY3LIBDIR python/$PY3LIBDIR"
for i in $dirs; do
if test -d $PY3EPREFIX/$PY3LIBDIR/$i; then
PY3LIB="$PY3EPREFIX/$PY3LIBDIR/$i"
break
fi
done
if test -z "$PY3LIB"; then
AC_MSG_RESULT([Not found])
else
AC_MSG_RESULT($PY3LIB)
fi
PY3LINK="-l$PY3VERSION"
fi
# Cygwin (Windows) needs the library for dynamic linking
case $host in
*-*-cygwin* | *-*-mingw*) PYTHON3DYNAMICLINKING="-L$PYLIB $PY3LINK"
DEFS="-DUSE_DL_IMPORT $DEFS" PY3INCLUDE="$PY3INCLUDE"
;;
*)PYTHON3DYNAMICLINKING="";;
esac
fi
AC_SUBST(PY3INCLUDE)
AC_SUBST(PY3LIB)
AC_SUBST(PY3LINK)
AC_SUBST(PYTHON3DYNAMICLINKING)
#----------------------------------------------------------------
# Look for Perl5
#----------------------------------------------------------------
@ -1856,11 +1953,17 @@ AC_SUBST(SKIP_OCTAVE)
SKIP_PYTHON=
if test -z "$PYINCLUDE" || test -z "$PYLIB" ; then
if (test -z "$PYINCLUDE" || test -z "$PYLIB") &&
(test -z "$PY3INCLUDE" || test -z "PY3LIB") ; then
SKIP_PYTHON="1"
fi
AC_SUBST(SKIP_PYTHON)
SKIP_PYTHON3=
if test -z "$PY3INCLUDE" || test -z "$PY3LIB" ; then
SKIP_PYTHON3="1"
fi
AC_SUBST(SKIP_PYTHON3)
SKIP_JAVA=
if test -z "$JAVA" || test -z "$JAVAC" || test -z "$JAVAINC" ; then