문제

I'm going out of my mind here. I expect to catch exceptions in C++ so that I can map them to a custom exception class in python. All I get now are python Exceptions. I cannot catch my Exceptions inside generated code???

program:

#!/usr/bin/python

import os
import sys
import hpsphal_python

prog = os.path.basename(__file__) + ": "

try:
    hal = hpsphal_python.System_getSystem()
    scs = hal.getStorageClusters()
    if len(scs) == 0:
        print >>sys.stderr, prog + "No storage clusters found."
        os._exit(-1)

    for sc in scs:
        print "sc: ", sc.getUUID()
        conts = sc.getControllers()
        for c in conts:
            try:
                c.setClock()
            except hpsphal_python.Exception as e:
                print "he: ", e.what()
            except RuntimeError as e:
                print "rt: ", e, e[0]
            except Exception as e:
                print "e: ", e, e[0]

    os._exit(0)
except Exception, e:
    print "E: ", e
    os._exit(-1)

output:

sc:  222367ad-0005-1000-95ab-415a34303736
e:  setControllerClock setControllerClock
e:  setControllerClock setControllerClock
sc:  MXQ04205MV_Con_0_Cluster
e:  setControllerClock setControllerClock

Same code in C++ that does in fact catch the Exceptions:

#include "time.h"

#include <iostream>
#include <map>
#include <set>
#include <string>
#include <exception>

#include <boost/foreach.hpp>
#include <boost/regex.hpp>
#include <boost/thread/thread.hpp>

#include "Exception.hpp"
#include "StorageCluster.hpp"
#include "Controller.hpp"
#include "System.hpp"

using namespace std;

int main (int argc, char *argv[])
{
    danAPI::SystemPtr danSystem;
    try {
        danSystem = danAPI::System::getSystem();
    }
    catch(danAPI::Exception& e) {
        cerr << "Unable to initialize danAPI" << e.what() << endl;
        return -1;
    }

    try {
        danAPI::StorageClusterPtrList danStorageClusters = danSystem->getStorageClusters();
        BOOST_FOREACH(danAPI::StorageClusterPtr sc, danStorageClusters)
        {
            danAPI::ControllerPtrList danStorageControllers = sc->getControllers();
            BOOST_FOREACH(danAPI::ControllerPtr c, danStorageControllers)
            {
                try {
                    c->setClock();
                }
                catch(danAPI::Exception& e) {
                    cerr << "HAL Exception: " << e.what() << endl;
                }
                catch(exception& e) {
                    cerr << "Standard Exception: " << e.what() << endl;
                }
            }
        }
    }
    catch(exception& e) {
        cerr << "Unable to get storage clusters: " << e.what() << endl;
    }

    return 0;
}

output:

HAL Exception: setControllerClock: SetClock exception: function failed (1)
/jenkins/workspace/ts1.4-hpsphal/storage-lib/src/Raptor.cpp: 1100
/jenkins/workspace/ts1.4-hpsphal/storage-lib/src/Raptor.cpp: 791
(1)
/jenkins/workspace/ts1.4-hpsphal/storage-lib/src/StorageCluster_Rcim.cpp: 2158

HAL Exception: setControllerClock: SetClock exception: function failed (1)
/jenkins/workspace/ts1.4-hpsphal/storage-lib/src/Raptor.cpp: 1100
/jenkins/workspace/ts1.4-hpsphal/storage-lib/src/Raptor.cpp: 791
(1)
/jenkins/workspace/ts1.4-hpsphal/storage-lib/src/StorageCluster_Rcim.cpp: 2158

The players:

custom Exception class
SWIG 2.0.12
boost 1.41 throw_exception

A snippet from my generated code:

  {
    try {
      (arg1)->setClock();
    } catch(danAPI::Exception& e) {
      std::cerr << "++++++" << std::endl;
    } catch(std::exception& e) {
      std::cerr << "++++++" << std::endl;
    } catch(boost::exception& e) {
      std::cerr << "++++++" << std::endl;
    } catch(...) {
      std::cerr << "++++++" << std::endl;
    }
  }
  resultobj = SWIG_Py_Void();
  return resultobj;
fail:
  return NULL;

Here's my .i file (hdrs macros are filled in with my header files)

%include "stdint.i"
%include "stl.i"
%include "std_string.i"
%include "std_vector.i"
%include "std_string.i"
%include "std_pair.i"
%include "std_set.i"
%include "typemaps.i"

%apply unsigned long long &OUTPUT { unsigned long long &firstCharInBuffer };
%apply unsigned long long &OUTPUT { unsigned long long &nextChar };
%exceptionclass danAPI::Exception;

%exception {
    try {
        $action
    }
    catch(danAPI::Exception &e)
    {
        SWIG_Python_Raise(SWIG_NewPointerObj(
            (new danAPI::Exception(static_cast<const danAPI::Exception&>(e))),
            SWIGTYPE_p_danAPI__Exception,SWIG_POINTER_OWN),
            "Exception", SWIGTYPE_p_danAPI__Exception);
       SWIG_fail;
    }
}

// need to define the templates for shared_ptr<T> before we define the
// various T's below; put in a common place so the various SWIG interfaces
// stay in sync
%include "hpsphal_ptrs.i"

%{
    ${hash_public_headers}
    using namespace danAPI;
%}

${percent_public_headers}

// need to define the vector types after we've defined the types
// themselves; moved to a common place to keep the various SWIG interfaces
// in sync
%include "hpsphal_vectors.i"

I ran my code in gdb, "catch throw". I saw a few exceptions that I catch internal to my library. There should have been 3 exceptions thrown by my library, then caught by my SWIG code.

This was caught internally:

#0  0x000000337c8bccb0 in __cxa_throw () from /usr/lib64/libstdc++.so.6
#1  0x00007ffff122a1ac in boost::throw_exception<danAPI::Exception> (e=...) at /usr/include/boost/throw_exception.hpp:64
#2  0x00007fffef398841 in danAPI::StorageClusterFactory::getStorageControllerType (this=0x7fffffffd6d0, path="/dev/sg4")
    at /home/chchr/src/hpsphal/storage-lib/src/StorageClusterFactory.cpp:247
#3  0x00007fffef398aa8 in danAPI::StorageClusterFactory::createStorageCluster (this=0x7fffffffd6d0, path="/dev/sg4",
    storclustpList=std::vector of length 1, capacity 1 = {...}, cluster=std::tr1::shared_ptr (empty) 0x0, err=...)
    at /home/chchr/src/hpsphal/storage-lib/src/StorageClusterFactory.cpp:308
#4  0x00007fffef3a262c in boost::_mfi::cmf4<void, danAPI::StorageClusterFactory, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, danAPI::ConstStorageClusterPtrList const&, danAPI::ConstStorageClusterPtr&, boost::exception_ptr&>::call<danAPI::StorageClusterFactory const* const, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::tr1::shared_ptr<danAPI::StorageCluster const>, std::allocator<std::tr1::shared_ptr<danAPI::StorageCluster const> > > const, std::tr1::shared_ptr<danAPI::StorageCluster const>, boost::exception_ptr> (this=0x896740, u=@0x896750, b1=
    "/dev/sg4", b2=std::vector of length 1, capacity 1 = {...}, b3=std::tr1::shared_ptr (empty) 0x0, b4=...)
    at /usr/include/boost/bind/mem_fn_template.hpp:547
#5  0x00007fffef3a2466 in boost::_mfi::cmf4<void, danAPI::StorageClusterFactory, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, danAPI::ConstStorageClusterPtrList const&, danAPI::ConstStorageClusterPtr&, boost::exception_ptr&>::operator()<danAPI::StorageClusterFactory const*> (
    this=0x896740, u=@0x896750, a1="/dev/sg4", a2=std::vector of length 1, capacity 1 = {...}, a3=std::tr1::shared_ptr (empty) 0x0, a4=...)
    at /usr/include/boost/bind/mem_fn_template.hpp:556
#6  0x00007fffef3a21d4 in boost::_bi::list5<boost::_bi::value<danAPI::StorageClusterFactory const*>, boost::_bi::value<char*>, boost::reference_wrapper<std::vector<std::tr1::shared_ptr<danAPI::StorageCluster const>, std::allocator<std::tr1::shared_ptr<danAPI::StorageCluster const> > > >, boost::reference_wrapper<std::tr1::shared_ptr<danAPI::StorageCluster const> >, boost::reference_wrapper<boost::exception_ptr> >::operator()<boost::_mfi::cmf4<void, danAPI::StorageClusterFactory, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, danAPI::ConstStorageClusterPtrList const&, danAPI::ConstStorageClusterPtr&, boost::exception_ptr&>, boost::_bi::list0> (this=0x896750, f=..., a=...) at /usr/include/boost/bind/bind.hpp:518
#7  0x00007fffef3a1e0d in boost::_bi::bind_t<void, boost::_mfi::cmf4<void, danAPI::StorageClusterFactory, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, danAPI::ConstStorageClusterPtrList const&, danAPI::ConstStorageClusterPtr&, boost::exception_ptr&>, boost::_bi::list5<boost::_bi::value<danAPI::StorageClusterFactory const*>, boost::_bi::value<char*>, boost::reference_wrapper<std::vector<std::tr1::shared_ptr<danAPI::StorageCluster const>, std::allocator<std::tr1::shared_ptr<danAPI::StorageCluster const> > > >, boost::reference_wrapper<std::tr1::shared_ptr<danAPI::StorageCluster const> >, boost::reference_wrapper<boost::exception_ptr> > >::operator() (this=0x896740) at /usr/include/boost/bind/bind_template.hpp:20
#8  0x00007fffef3a19cc in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::cmf4<void, danAPI::StorageClusterFactory, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, danAPI::ConstStorageClusterPtrList const&, danAPI::ConstStorageClusterPtr&, boost::exception_ptr&>, boost::_bi::list5<boost::_bi::value<danAPI::StorageClusterFactory const*>, boost::_bi::value<char*>, boost::reference_wrapper<std::vector<std::tr1::shared_ptr<danAPI::StorageCluster const>, std::allocator<std::tr1::shared_ptr<danAPI::StorageCluster const> > > >, boost::reference_wrapper<std::tr1::shared_ptr<danAPI::StorageCluster const> >, boost::reference_wrapper<boost::exception_ptr> > > >::run (this=0x896610) at /usr/include/boost/thread/detail/thread.hpp:56
#9  0x00007fffed8c2d97 in thread_proxy () from /usr/lib64/libboost_thread-mt.so.5
#10 0x000000337a007851 in start_thread () from /lib64/libpthread.so.0
#11 0x00000033794e811d in clone () from /lib64/libc.so.6

Then I should have gotten 2 more from setControllerClock() before:

#0  0x000000337c8bccb0 in __cxa_throw () from /usr/lib64/libstdc++.so.6
#1  0x00007ffff143fc4c in swig::SwigPyIteratorClosed_T<__gnu_cxx::__normal_iterator<std::tr1::shared_ptr<danAPI::Controller>*, std::vector<std::tr1::shared_ptr<danAPI::Controller>, std::allocator<std::tr1::shared_ptr<danAPI::Controller> > > >, std::tr1::shared_ptr<danAPI::Controller>, swig::from_oper<std::tr1::shared_ptr<danAPI::Controller> > >::value (this=0x87bf50) at /home/chchr/src/hpsphal/build/python/hpsphalPYTHON_wrap.cxx:4894
#2  0x00007ffff101ddb7 in swig::SwigPyIterator::next (this=0x87bf50) at /home/chchr/src/hpsphal/build/python/hpsphalPYTHON_wrap.cxx:3472
#3  0x00007ffff07a083c in _wrap_SwigPyIterator_next (args=0x7ffff7f69850) at /home/chchr/src/hpsphal/build/python/hpsphalPYTHON_wrap.cxx:14301
#4  0x000000337b8deb24 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.6.so.1.0
#5  0x000000337b8e0797 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.6.so.1.0
#6  0x000000337b86edb0 in ?? () from /usr/lib64/libpython2.6.so.1.0
#7  0x000000337b844303 in PyObject_Call () from /usr/lib64/libpython2.6.so.1.0
#8  0x000000337b85970f in ?? () from /usr/lib64/libpython2.6.so.1.0
#9  0x000000337b844303 in PyObject_Call () from /usr/lib64/libpython2.6.so.1.0
#10 0x000000337b89d5eb in ?? () from /usr/lib64/libpython2.6.so.1.0
#11 0x000000337b8da458 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.6.so.1.0
#12 0x000000337b8e0797 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.6.so.1.0
#13 0x000000337b8e0872 in PyEval_EvalCode () from /usr/lib64/libpython2.6.so.1.0
#14 0x000000337b8fbbbc in ?? () from /usr/lib64/libpython2.6.so.1.0
#15 0x000000337b8fbc90 in PyRun_FileExFlags () from /usr/lib64/libpython2.6.so.1.0
#16 0x000000337b8fd17c in PyRun_SimpleFileExFlags () from /usr/lib64/libpython2.6.so.1.0
#17 0x000000337b909c32 in Py_Main () from /usr/lib64/libpython2.6.so.1.0
#18 0x000000337941ecdd in __libc_start_main () from /lib64/libc.so.6
#19 0x0000000000400649 in _start ()

catch throw from c++ program:

Catchpoint 1 (exception thrown), 0x000000337c8bccb0 in __cxa_throw () from /usr/lib64/libstdc++.so.6
(gdb) bt
#0  0x000000337c8bccb0 in __cxa_throw () from /usr/lib64/libstdc++.so.6
#1  0x00007ffff6e9610c in boost::throw_exception<danAPI::Exception> (e=...) at /usr/include/boost/throw_exception.hpp:64
#2  0x00007ffff72a065f in danAPI::Controller_Rcim::setClock (this=0x641430) at /home/chchr/src/hpsphal/storage-lib/src/Controller_Rcim.cpp:2128
#3  0x00000000004072ac in main (argc=1, argv=0x7fffffffe728) at /home/chchr/src/hpsphal/python/foo.cpp:39
도움이 되었습니까?

해결책

In your .i file, your %exception block puts a try around the function, then in each catch clause, it prints the error then continues execution as if there had been no exception. This is surely not what you intended, because the result is that you won't get any exceptions propagated to Python (how could you? you've told SWIG to generate code to ignore them). Use exception.i, as explained in section 11.1.7 of the SWIG manual. For example,

%include exception.i       

%exception {
    try {
        $action
    } catch(const danAPI::Exception& e) {
        SWIG_exception(SWIG_ValueError, "Dan API exception");
    } catch(const std::exception& e) {
        SWIG_exception(SWIG_UnknownError, "Standard exception");
    } catch(const boost::exception& e) {
        SWIG_exception(SWIG_UnknownError, "Boost exception");
    } catch(...) {
        SWIG_exception(SWIG_RuntimeError, "Unknown exception");
    }
}

I've never looked at the code generated but my guess is that SWIG_exception causes some flag to be set, which SWIG checks for after execution of your $action, if set then SWIG uses Python API to throw a Python exception.

Update:

If you never see even the error message and you don't get to the catch clause then your C++ library is not throwing an exception. The issue is not the wrapper code (setControllerClock), it is your own C++ library code for setClock, or perhaps you are not calling it in a context that would raise the exception. Your issue is not related to generated code, SWIG, or Python. It is your library.

To prove this: put a throw std::runtime_error("test") just after your $action line. You will end up in the second catch clause, and e.what() will be "test":

%exception {
    try {
        $action
        throw std::runtime_error("test");
    } catch(const danAPI::Exception& e) {
        SWIG_exception(SWIG_ValueError, "Dan API exception");
    } catch(const std::exception& e) {
        SWIG_exception(SWIG_UnknownError, "Standard exception");
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top