【问题标题】:Why am I losing exceptions with SWIG, C++, python为什么我会丢失 SWIG、C++、python 的异常
【发布时间】:2014-04-14 06:09:51
【问题描述】:

我在这里疯了。我希望在 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

我生成的代码中的一个 sn-p:

  {
    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

【问题讨论】:

    标签: python c++ exception boost swig


    【解决方案1】:

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

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

    【讨论】:

    • 我剥离了代码进行调试。我在生成的代码中根本没有到达 catch() 块。我从来没有在标准错误中看到“++++”,我期待看到我的库和我的包装代码之间抛出的异常。您是正确的,当前编写的包装器代码不会引发异常。
    • 问题不在于包装代码,而在于您的 C++ 代码。如果您从未到达您的 catch 块,那么您的 C++ 函数不会引发异常。在您的 $action 行之后放置一个throw std::runtime_error("test"),它将起作用。问题是 setControllerClock 调用的 C++ 函数没有抛出。这似乎与生成的代码无关。
    • 现在我们正在讨论让我难过的问题。我将打印代码放在从未执行的 $action 之后。我在上面附加了 C++ 代码,它与 python 代码做同样的事情(成功地)。此外,python 代码的输出告诉我,我从应该从中捕获 C++ 异常的方法中捕获了 python 异常。
    • @ChipChristian 我已经更新了我的帖子,也许现在会更清楚了。
    • 我从你上次的更新中注意到“setClock”和“setControllerClock”的分离仍然存在,所以我回到我原来的python程序,发现我没有在方法时调整方法名称从集群转移到控制器!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 2023-03-14
    • 2014-08-23
    • 2014-06-10
    相关资源
    最近更新 更多