我使用SWIG和Numpy。我定义了一个名为inplace()
的C函数来快速处理数据数组,我想做一些错误检查(如果两个数组具有相同的维度)。
我在%rename
文件中使用%inline
和.i
。据我了解,重命名应该映射函数名称,因此每次有人使用inplace
时,都会运行safe_inplace
并检查错误。
但它不起作用:(。至于我注意到,safe_inplace没有执行,python直接运行inplace
而没有触及函数的安全版本。
# .i
%include "inplace.h"
%rename (inplace) safe_inplace;
%inline %{
void safe_inplace(int* datain, int in_dx, int in_dy, int in_dz,
int* dataout, int out_dx, int out_dy)
{
if ((in_dx != out_dx) || (in_dy != out_dy)) {
PyErr_Format(PyExc_ValueError, /*... messgage*/)
return;
}
inplace( /* .. pass the arguments to original function*/ );
}
头文件:
# .h
void inplace(int* datain, int in_dx, int in_dy, int in_dz, int* dataout, int out_dx, int out_dy);
的Python:
#.py
inplace.inplace(a,b)
我可以找到我修改的原始示例here
答案 0 :(得分:4)
您的原始方法很接近,但您可能希望SWIG不要完全包装该功能的原始版本。
我汇总了一个稍微简单的例子来说明这是如何工作的。鉴于头文件:
void foo();
我们想要包装它,以便在调用真实版本之前调用稍微修改过的版本。
最简单的方法是永远实际上显示SWIG头文件完全用于包装,仅用于编译包装器,例如:
%module test
%{
#include "test.h"
#include <iostream>
%}
%rename (foo) foo_safe;
%inline %{
void foo_safe() {
std::cout << "Hello world" << std::endl;
foo(); // Calls the foo() from test.h, as you'd hope
}
%}
如果您不想删除%include
(例如,您也在该头文件中还有其他事项),您可以执行以下操作:
%module test
%{
#include "test.h"
#include <iostream>
%}
%rename (unsafe_foo) foo;
%include "test.h"
%rename (foo) foo_safe;
%inline %{
void foo_safe() {
std::cout << "Hello world" << std::endl;
foo();
}
%}
将foo
的实际实现公开为unsafe_foo
。
如果没有理由让Python用户能够永远致电%ignore
,您可以使用unsafe_ignore
:
%module test
%{
#include "test.h"
#include <iostream>
%}
%rename (foo) foo_safe;
%inline %{
void foo_safe() {
std::cout << "Hello world" << std::endl;
foo();
}
%}
%ignore foo;
%include "test.h"
最后看起来你的目标实际上只是在调用真正的C函数之前运行一些代码。如果是这种情况,有几种方法也可以做到这一点,例如你可以在使用pythonprepend
进行真正的函数调用之前添加python代码:
%feature("pythonprepend") foo() %{
print "hello world"
# check args and raise possibly
%}
或者最后你也可以使用%exception
功能,例如(未经测试):
%exception inplace {
// Check args and possibly throw
$action
}
$action
将自动替换为真实的来电。