为什么我丢失异常与SWIG, c++, python

Why am I losing exceptions with SWIG, C++, python

本文关键字:SWIG c++ python 异常 为什么      更新时间:2023-10-16

我都快疯了。我希望在c++中捕获异常,以便可以将它们映射到python中的自定义异常类。我现在得到的都是python异常。我不能捕获我的异常内部生成的代码??

计划:

#!/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)
输出:

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

与c++中捕获异常的代码相同:

#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;
}
输出:

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
玩家

:

custom Exception class
SWIG 2.0.12
boost 1.41 throw_exception

生成的代码片段:

  {
    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;

这是我的。i文件(hdrs宏填充与我的头文件)

%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"

我在gdb中运行我的代码,"catch throw"。我在库内部发现了一些异常。我的库应该抛出3个异常,然后被我的SWIG代码捕获。

内部捕获:

#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

那么我应该从setControllerClock()()之前得到更多的2:

#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 ()

c++程序的catch throw:

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

在您的。i文件中,您的%exception块将try放在函数周围,然后在每个catch子句中,它打印错误然后继续执行,就好像没有异常一样。这肯定不是你想要的,因为结果是你不会得到任何异常传播到Python(你怎么可能?您已经告诉SWIG生成代码来忽略它们)。使用异常。i,如SWIG手册第11.1.7节所述。例如,

%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");
    }
}

我从来没有看过生成的代码,但我的猜测是SWIG_exception导致一些标志被设置,SWIG在执行$action后检查,如果设置,那么SWIG使用Python API抛出Python异常。

更新:

如果你从来没有看到错误信息,也没有看到catch子句,那么你的c++库就没有抛出异常。问题不在于包装器代码(setControllerClock),而在于您自己的setClock的c++库代码,或者您没有在会引发异常的上下文中调用它。您的问题与生成的代码、SWIG或Python无关。这是你的图书馆。

为了证明这一点:在$action行后面放一个throw std::runtime_error("test")。您将在第二个catch子句中结束,并且e.what()将变为"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");