python异常捕获,在C ++中捕获Python异常

I am developing a server-client application in which the client calls a server's API which gives a Python interface for user input. It means the client interface and server interface is written in Python whereas the socket code is in C++.

On the server side:-

I have a class, Test, in C++ and this class is inherited in Python named TestPython using director feature of SWIG.

Also I have an exception class MyException in C++.

Now a function of TestPython class throws MyException() from Python code.

I want to handle exception thrown from Python in C++ code using SWIG.

Below is code snippet:

C++ Code-

class MyException

{

public:

string errMsg;

MyException();

MyException(string);

~MyException();

};

class Test

{

int value;

public:

void TestException(int val);

Test(int);

};

Python Code -

class TestPython(Test):

def __init__(self):

Test.__init__(self)

def TestException(self,val):

if val > 20:

throw MyException("MyException : Value Exceeded !!!")

else:

print "Value passed = ",val

Now, if the TestException() function is called, it should throw MyException. I want to handle this MyException() exception in my C++ code.

So can anyone suggest my how to do that, I mean what should I write in my *.i(interface) file to handle this.

The above TestException() written in Python is called by the client, so I have to notify the client if any exception is thrown by the server.

解决方案

To do this you basically need to write a %feature("director:except") that can handle a Python exception and re-throw it as a C++ one. Here's a small but complete example:

Suppose we have the following header file we wish to wrap:

#include

#include

class MyException : public std::exception {

};

class AnotherException : public std::exception {

};

class Callback {

public:

virtual ~Callback() { std::cout << "~Callback()" << std:: endl; }

virtual void run() { std::cout << "Callback::run()" << std::endl; }

};

inline void call(Callback *callback) { if (callback) callback->run(); }

And this Python code that uses it:

import example

class PyCallback(example.Callback):

def __init__(self):

example.Callback.__init__(self)

def run(self):

print("PyCallback.run()")

raise example.MyException()

callback = PyCallback()

example.call(callback)

We can define the following SWIG interface file:

%module(directors="1") example

%{

#include "example.h"

%}

%include "std_string.i"

%include "std_except.i"

%include "pyabc.i"

// Python requires that anything we raise inherits from this

%pythonabc(MyException, Exception);

%feature("director:except") {

PyObject *etype = $error;

if (etype != NULL) {

PyObject *obj, *trace;

PyErr_Fetch(&etype, &obj, &trace);

Py_DecRef(etype);

Py_DecRef(trace);

// Not too sure if I need to call Py_DecRef for obj

void *ptr;

int res = SWIG_ConvertPtr(obj, &ptr, SWIGTYPE_p_MyException, 0);

if (SWIG_IsOK(res) && ptr) {

MyException *e = reinterpret_cast< MyException * >(ptr);

// Throw by pointer (Yucky!)

throw e;

}

res = SWIG_ConvertPtr(obj, &ptr, SWIGTYPE_p_AnotherException, 0);

if (SWIG_IsOK(res) && ptr) {

AnotherException *e = reinterpret_cast< AnotherException * >(ptr);

throw e;

}

throw Swig::DirectorMethodException();

}

}

%feature("director") Callback;

%include "example.h"

Which handles an error from a director call, looks to see if it was one of our MyException instances and then re-throws the pointer if it was. If you have multiple types of exception being thrown then you will probably need to use PyErr_ExceptionMatches to work out what type it is first.

We could throw also by value or reference using:

// Throw by value (after a copy!)

MyException temp = *e;

if (SWIG_IsNewObj(res))

delete e;

throw temp;

instead, but note that if you threw a subclass of MyException in Python this would fall foul of the object slicing problem.

I'm not quite sure if the code is 100% correct - in particular I think the reference counting is correct, but I could be wrong.

Note: In order to make this example work (%pythonabc wouldn't work otherwise) I had to call SWIG with -py3. This in turn meant I had to upgrade to SWIG 2.0, because my installed copy of Python 3.2 had removed some deprecated functions from the C-API that SWIG 1.3.40 called.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值