【发布时间】:2016-06-29 02:10:51
【问题描述】:
以下是我的 C API 中的函数示例:
int do_something(struct object *with_this)
struct object *get_something(struct object *from_this)
do_something 将返回 0 表示成功或 -1 并设置 errno 表示失败。 get_something 将在成功时返回一个有效指针,或者 NULL 并设置 errno 为失败。
我使用 SWIG 2.0 来生成 python 绑定。对于do_something 绑定,我希望它在失败时返回基于errno 的异常,如果成功则返回Python None 对象。对于get_something 绑定,我希望它在失败时返回基于errno 的异常,如果成功则返回不透明对象。
问题是如何让 SWIG 为我完成所有这些魔法?
目前我正在使用 SWIG 2.0。
我可以使用%exception 并为每个符号定义不同的异常,但我希望它基于返回类型。我会有很多 API 函数,我不想一一列举。所以我可以为每个符号执行此操作:
%exception do_something {
$action
if (result < 0) {
return PyErr_SetFromErrno(PyExc_RuntimeError);
}
}
%exception get_something {
$action
if (result == NULL) {
return PyErr_SetFromErrno(PyExc_RuntimeError);
}
}
如果我能做这样的事情会更好(就像你可以用 %typemap 做的那样):
%exception int {
$action
if (result < 0) {
return PyErr_SetFromErrno(PyExc_RuntimeError);
}
}
%exception struct object * {
$action
if (result == NULL) {
return PyErr_SetFromErrno(PyExc_RuntimeError);
}
}
我可以这样做吗?如果我有这样的东西,那么就会处理异常。而且我相信我的get_something 绑定会很完美。
如果我使用%typemap,我的do_something 绑定仍然需要这样的东西才能返回Python None 对象:
%typemap(out) int {
$result = Py_BuildValue("");
}
我正在寻找的魔法是存在的,还是我做错了?有没有更好的方法来做到这一点?
【问题讨论】:
-
相当肯定
%exception是您的用例的红鲱鱼,您想在%typemap(out)甚至%pythoncode内完成所有操作。如果没有人超过我,我会尽量记住为你写一个正确的答案。 -
感谢柔印。我已经尝试过
typemap(out),但问题是我必须重新实现类型处理,而我不想为get_something的情况这样做。对于get_something的情况,我只想处理异常但仍按原样处理类型。 -
我知道你在担心什么,我会考虑一下,然后给出一些解决方案。
-
随机评论:您是否尝试使用这一系列函数来模拟 OO 行为,并将隐式
this参数作为所有函数的第一个参数?您可能可以在 Python 界面中做一些更简洁的事情来拯救 Python 开发人员,即使您愿意,C 也不是真正的 OO。 (但这将是另一个问题) -
@Flexo 不完全是。我在这里的应用程序是我有一个使用下面的对象的 C API。重要的部分是我想以几乎原样使用 Python 的方式展示 C API。 Python 将使用PyCapsules 在 C API 和 Python 层之间来回传递这个不透明的对象。所有函数都将使用mutator/accessor 方法来保持不透明性。所以我希望这个原样能够使用EAFP 原则。