我正在尝试使用 swig 为一些 C++ 代码创建 python 绑定(bind)。我似乎遇到了一个问题,试图从我拥有的一些访问器函数创建 python 属性,如下所示:
class Player {
public:
void entity(Entity* entity);
Entity* entity() const;
};
我尝试使用 python 属性函数创建一个属性,但似乎 swig 生成的包装类与它不兼容,至少对于 setter 而言。
如何使用 swig 创建属性?
最佳答案
有一种简单的方法可以从 swig 方法中创建 python 属性。
假设 C++ 代码 Example.h:
C++ header
class Example{
public:
void SetX(int x);
int GetX() const;
};
让我们将此 setter 和 getter 转换为 python 属性“x”。诀窍在于 .i 文件。我们添加了一些“swiggy”内联 Python 代码(使用 %pythoncode),这些代码插入到生成的 Python 类的主体中(在自动生成的 Python 代码中)。
Swig 包装 Example.i
%module example
%{
#include "example.h"
%}
class Example{
public:
void SetX(int x);
int GetX() const;
%pythoncode %{
__swig_getmethods__["x"] = GetX
__swig_setmethods__["x"] = SetX
if _newclass: x = property(GetX, SetX)
%}
};
查看python代码:
python 测试代码
import example
test = example.Example()
test.x = 5
print "Ha ha ha! It works! X = ", repr(test.x)
就是这样!
让它更简单!
无需重写类定义。感谢 Joshua 的建议,可以使用 SWIG 指令 %extend ClassName { }。
Swig 包装 Example.i
%module example
%{
#include "example.h"
%}
%extend Example{
%pythoncode %{
__swig_getmethods__["x"] = GetX
__swig_setmethods__["x"] = SetX
if _newclass: x = property(GetX, SetX)
%}
};
隐藏 setter 和 getter 函数
正如大家所见,test.GetX() 和 test.SetX() 在转换后仍然存在。可以通过以下方式隐藏它们:
a) 使用 %rename 重命名函数,在开头添加“_”,从而使 python 的方法“私有(private)”。在 SWIG 界面 .i 例子.i
...
class Example{
%rename(_SetX) SetX(int);
%rename(_GetX) GetX();
...
(%rename 可以放在某个单独的地方,以节省将此类转换为不需要这些'_'的其他语言的可能性)
b) 或者可以使用 %feature("shadow")
为什么会这样?
为什么我们必须使用这些东西通过 SWIG 将方法转换为属性? 如前所述,SWIG 自私地覆盖了 _setattr_,因此必须使用 _swig_getmethods_ 和 _swig_setmethods_ 进行注册功能并保持在swig方式。
为什么人们更喜欢这种方式?
上面列出的方法,尤其是使用 PropertyVoodoo 的方法是……就像烧房子煎鸡蛋一样。它还破坏了类布局,因为必须创建继承的类才能从 C++ 方法中创建 python 属性。我的意思是如果类Cow返回类Milk并且继承类是MilkWithProperties(Milk),如何让Cow产生MilkWithProperties?
这种方法允许人们:
- 明确控制要转换为 python 属性的 C++ 方法
- 转换规则位于 swig interface(*.i) 文件中,它们应该在的地方
- 一个自动生成的 .py 文件
- 在 swig 生成的 .py 文件中保持插入的 swig 语法
- 如果将库包装成其他语言,则忽略%pythoncode
更新 在较新的版本中,SWIG 放弃了 _swig_property,因此只需使用 property。它与旧版本的 swig 相同。我已经换了帖子。
关于c++ - Python 属性和 Swig,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1183716/