我有很多C / C ++类要使用Swig导出到python。我注意到默认情况下,Swig不为包装类生成__hash__
方法,因此使用默认哈希,即包装器对象的id(即其内存地址或类似内容)。这意味着如果我最终得到两个包含相同C对象的python对象,它们会在dicts中以不同的方式进行散列等等,这很奇怪并导致难以发现的错误。
我可以使用更好的__hash__
:
%extend Foo {
bool __eq__(const Foo &other) { return $self == &other; }
bool __ne__(const Foo &other) { return $self != &other; }
long __hash__() { return (long) $self; } // hash: just address of C struct
}
(我也认为eq应默认基于C结构地址进行比较,而不是包装器的地址。)
我的问题是:有没有办法告诉Swig扩展这样的所有类?或者我必须一次做一个?
我想第二个问题是:为什么不自动执行此操作?默认行为有用吗?我发现它不是。
答案 0 :(得分:5)
我不知道有办法做到这一点,只是因为它很少是你想要的(“所有课程”可能包括的比你意识到的更多并且真的有意)。但是,SWIG确实支持自己的宏系统,因此您可以执行以下操作:
%define PY_HASHABLE(TypeName)
%extend TypeName {
bool __eq__(const TypeName &other) { return $self == &other; }
bool __ne__(const TypeName &other) { return $self != &other; }
long __hash__() { return (long) $self; } // hash: just address of C struct
}
%enddef
然后你会做
#if defined(SWIGPYTHON)
PY_HASHABLE(Foo)
PY_HASHABLE(Bar)
#endif
等。您可以为给定的类具有多个扩展子句,因此上述内容不会干扰其他扩展。