gpt4 book ai didi

c++ - boost::python 导出自定义异常

转载 作者:IT老高 更新时间:2023-10-28 20:27:48 25 4
gpt4 key购买 nike

我目前正在使用 Boost.Python 为 Python 编写 C++ 扩展。此扩展中的函数可能会生成包含有关错误信息的异常(不仅仅是描述所发生情况的人类可读字符串)。我希望我可以将这个异常导出到 Python,这样我就可以捕获它并使用额外的信息做一些事情。

例如:

import my_cpp_module
try:
my_cpp_module.my_cpp_function()
except my_cpp_module.MyCPPException, e:
print e.my_extra_data

不幸的是,Boost.Python 似乎将所有 C++ 异常(它们是 std::exception 的子类)转换为 RuntimeError。我意识到 Boost.Python 允许实现自定义异常转换,但是需要使用 PyErr_SetObject ,它需要一个 PyObject* (用于异常的类型)和一个 PyObject* (对于异常的值)——我都不知道如何从我的 Boost.Python 类中获取它们。也许有一种我还没有找到的方法(这会很棒)。否则有谁知道如何导出自定义 C++ 异常以便我可以在 Python 中捕获它?

最佳答案

解决方案是像创建任何普通 C++ 类一样创建异常类

class MyCPPException : public std::exception {...}

诀窍是所有 boost::python::class_ 实例都持有对对象类型的引用,该引用可通过它们的 ptr() 函数访问。你可以在使用 boost::python 注册类时得到它,如下所示:

class_<MyCPPException> myCPPExceptionClass("MyCPPException"...);
PyObject *myCPPExceptionType=myCPPExceptionClass.ptr();
register_exception_translator<MyCPPException>(&translateFunc);

最后,当您将 C++ 异常转换为 Python 异常时,请执行以下操作:

void translate(MyCPPException const &e)
{
PyErr_SetObject(myCPPExceptionType, boost::python::object(e).ptr());
}

这是一个完整的工作示例:

#include <boost/python.hpp>
#include <assert.h>
#include <iostream>

class MyCPPException : public std::exception
{
private:
std::string message;
std::string extraData;
public:
MyCPPException(std::string message, std::string extraData)
{
this->message = message;
this->extraData = extraData;
}
const char *what() const throw()
{
return this->message.c_str();
}
~MyCPPException() throw()
{
}
std::string getMessage()
{
return this->message;
}
std::string getExtraData()
{
return this->extraData;
}
};

void my_cpp_function(bool throwException)
{
std::cout << "Called a C++ function." << std::endl;
if (throwException)
{
throw MyCPPException("Throwing an exception as requested.",
"This is the extra data.");
}
}

PyObject *myCPPExceptionType = NULL;

void translateMyCPPException(MyCPPException const &e)
{
assert(myCPPExceptionType != NULL);
boost::python::object pythonExceptionInstance(e);
PyErr_SetObject(myCPPExceptionType, pythonExceptionInstance.ptr());
}

BOOST_PYTHON_MODULE(my_cpp_extension)
{
boost::python::class_<MyCPPException>
myCPPExceptionClass("MyCPPException",
boost::python::init<std::string, std::string>());
myCPPExceptionClass.add_property("message", &MyCPPException::getMessage)
.add_property("extra_data", &MyCPPException::getExtraData);
myCPPExceptionType = myCPPExceptionClass.ptr();
boost::python::register_exception_translator<MyCPPException>
(&translateMyCPPException);
boost::python::def("my_cpp_function", &my_cpp_function);
}

这是调用扩展的 Python 代码:

import my_cpp_extension
try:
my_cpp_extension.my_cpp_function(False)
print 'This line should be reached as no exception should be thrown.'
except my_cpp_extension.MyCPPException, e:
print 'Message:', e.message
print 'Extra data:',e.extra_data

try:
my_cpp_extension.my_cpp_function(True)
print ('This line should not be reached as an exception should have been' +
'thrown by now.')
except my_cpp_extension.MyCPPException, e:
print 'Message:', e.message
print 'Extra data:',e.extra_data

关于c++ - boost::python 导出自定义异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2261858/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com