使用boost python,我在我的python包装器中添加了一个属性,其值来自枚举类型,例如:
scope().attr("myconstant")=some_namespace::some_class::some_enum_value;
但是当我导入我的python模块时出现运行时错误:
terminate called after throwing an instance of 'boost::python::error_already_set'
在其他线程之后,我将上面的内容放在try / catch中但是没有捕到任何东西来调用PyErr_Fetch。我仍然好奇原始python错误发生的地方。
事实证明我必须做
scope().attr("myconstant")=int(some_namespace::some_class::some_enum_value);
然后它运行。
另一个,但我认为相关的问题是,如果你在python包装器中导出一个返回C ++枚举的C ++函数,但是你没有导出那个枚举,一切都没问题,直到你从python调用这个函数。然后boost会生成一个关于未找到类型的python异常。
很明显,在运行时做一些事情似乎(对我来说)应该在编译时完成。这两个问题都很难诊断。有谁知道发生了什么?随着运行时发生的事情越来越多,我预计,如果我直接使用python扩展API,我是否会遇到boost python的性能问题?除了性能之外,我还担心提升python代码会有更多的错误,直到运行时才能找到,直到python扩展代码才会有。
另一方面,所有这些动态类型绑定是否有一些大的收获?很明显,有一个很好的boost接口用于编写我自己的python扩展 - 但是所有这些动态绑定是否更容易将新的boost python包装器添加到现有系统中,然后使用python扩展API直接编写包装器?
答案 0 :(得分:1)
使用Python支持动态名称解析,我认为用Boost.python强制编译时断言是相当困难的。 C ++代码在运行时向Python公开,Boost.Python类型转换可能已在不同的模块中注册,在运行时单独加载。
Boost.Python,甚至是Python C-API,在运行时执行大部分工作。 Boost.Python不会将错误延迟到运行时,而不是Python C-API。当Python导入Boost.Python模块时,BOOST_PYTHON_MODULE
代码执行,创建类型,注册类型标识,并注册允许Python和C ++对象之间无缝互操作的函数。总的来说,C-API或任何其他Python语言绑定工具集仍然需要相同的设置过程。由于Boost.Python提供了一种高级通用解决方案,因此与为应用程序量身定制的手写绑定相比,它可能会更加臃肿。
我个人的经验是,使用Boost.Python扩展现有系统比直接编写Python C-API更容易。我必须编写明显更少的代码,从而减少错误,同时提高可读性和可维护性。例如,考虑官方Python Extending Simple Example:
#include <stdlib.h> // system
#include <Python.h>
static PyObject*
spam_system(PyObject* self, PyObject* args)
{
const char* command;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
return Py_BuildValue("i", system(command));
}
static PyMethodDef SpamMethods[] =
{
{"system", &spam_system, METH_VARARGS,
"Execute a shell command."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC
initspam(void)
{
Py_InitModule("spam", SpamMethods);
}
和Boost.Python中的等价物:
#include <stdlib.h> // system
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(spam)
{
boost::python::def("system", &system);
}