Re: Python iterator / SWIG newbie

William S Fulton <[email protected]> Sun, 20 Jun 2021 09:44:24 +0100
Newsgroups gmane.comp.programming.swig
Message-ID <CANGqftCXR8R8OujVDok-bW2E_GQdkv2cxs+A9qy0Y9ByzZY5UA@mail.gmail.com>
On Sat, 19 Jun 2021 at 01:28, <[email protected]> wrote:

> Dear Swig Users,
>
>
>
> I am trying to wrap an Oracle library for Python.  They have a C++
> iterator that expects a reference for the next value and returns a
> boolean.  I thought it would be as easy as writing a new C++ class that
> contained an instance of the object in question and extending the class to
> create a new instance of my iterator class.  I implemented the new iterator
> class as a C++ inline class (header) below:
>
>
>
> namespace DbXml {
>
>
>
>   class XmlResultsIterator
>
>   {
>
>   public:
>
>
>
>     XmlValue current;  // holds current value of iterator
>
>     XmlResults *iterable;  // object over which we will iterate
>
>
>
>     inline XmlResultsIterator(XmlResults *results) {
>
>       iterable = results;  // store the object over which we will iterate
>
>     }
>
>
>
>     inline XmlValue *__next__() {
>
>       // __next__  [comments deleted for brevity]
>
>
>
>       XmlValue *retval;
>
>       bool ok = iterable->next(current);  // get next
>
>       if (ok)
>
>               retval = &current;
>
>       else {
>
>               PyErr_SetNone(PyExc_StopIteration); // no more values, stop
> iteration error
>
>               retval = nullptr;
>
>       }
>
>       return retval;
>
>     }
>
>   };
>
> }
>
>
>
> I %include the header, and the iteration starts fine.  However, when I hit
> the ok == false case, I see the following error in Python 3.9:
>
>
>
>   File "u:\Users\...\Python39\lib\site-packages\dbxml.py", line 1662, in
> __next__
>
>     return _dbxml.XmlResultsIterator___next__(self)
>
> SystemError: <built-in function XmlResultsIterator___next__> returned a
> result with an error set
>
>
>
> During handling of the above exception, another exception occurred:
>
> Traceback (most recent call last):
>
>   File "c:\apps\develop\dbxml-6.1.4\dbxml\examples\python3\examples.py",
> line 496, in <module>
>
>     do_example(number)
>
>   File "c:\apps\develop\dbxml-6.1.4\dbxml\examples\python3\examples.py",
> line 474, in do_example
>
>     globals()["example%02d" % number]()
>
>   File "c:\apps\develop\dbxml-6.1.4\dbxml\examples\python3\examples.py",
> line 69, in example02
>
>     for value in results:
>
> TypeError: catching classes that do not inherit from BaseException is not
> allowed
>
>
>
> I suspect that I am doing something stupid like not including a %except or
> %typemap that I need, but I’ve been going over the documentation as well as
> examples in user groups and it is not clear to me what I am doing wrong.
> Directors are enabled (%module(directors=”1”,…)).
>
>
>
Look in the docs at %exception and add this before __next__ is parsed:

%exception DbXml::XmlResultsIterator::__next__() %{
$action
if (!$result) SWIG_fail;
%}

It allows you to check for nullptr return from __next__ before calling any
Python APIs.

William

_______________________________________________
Swig-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/swig-user