12

我可以将 C++enum作为真实实体而不是一组常量公开给 SWIG,以便我可以在 python 代码中枚举它们吗?

4

3 回答 3

12

我遇到了同样的问题。我希望 SWIG 很快支持 C++11 的enum class.

这是说服 SWIG 将枚举放入结构中的 hack:

#ifdef SWIG
%rename(MyEnum) MyEnumNS;
#endif

struct MyEnumNS
{
    enum Value { Value1, Value2, Value3 };
};
typedef MyEnumNS::Value MyEnum;

.cpp您现在必须使用MyEnum::Value1的代码中,在 Python 代码中它是MyEnum.Value1. 尽管令人费解,但typedef可以避免更改在任何地方都使用枚举的现有代码,并且 SWIG %rename 使枚举在 SWIG 包装器中具有相同的名称。

在 Python 中,您可以使用一些代码枚举值:

def values(enum):
    return [(k,v) for k,v in vars(enum).items() if isinstance(v,int)]

它不漂亮,我希望看到更好的解决方案。

于 2012-11-15T21:08:56.483 回答
5

我们可以制作一些东西,让您在 Python 中枚举它,而对它包装的 C++ 头文件的侵入相对较少。例如,如果我们有一个头文件:

#ifndef PYTHON_ENUM 
#define PYTHON_ENUM(x) enum x
#endif

PYTHON_ENUM(TestName) {
  foo=1,
  bar=2
};

PYTHON_ENUM(SomeOtherName) {
  woof,
  moo
};

它扩展为 C++ 中的常规枚举,但足以作为头文件在 Python 中公开枚举成员。

使用%typemap(constcode)我们可以为枚举注入一些额外的东西到我们的 Python 模块中,但是我们需要知道枚举的名称才能做到这一点;它的 SWIG typeinfo 对象就好像它是一个int. 因此,我们在PYTHON_ENUM宏中使用了一些技巧来将枚举的名称存储在自定义类型映射中。

%module test
%{
#include "test.h"
%}

%typemap(constcode) int {
  PyObject *val = PyInt_FromLong(($type)($value));
  SWIG_Python_SetConstant(d, "$1", val);
  const char *name = "$typemap(enum_realname,$1_type)";
  PyObject *e = PyDict_GetItemString(d, name);
  if (!e) PyDict_SetItemString(d, name, e = PyDict_New());
  PyDict_SetItemString(e, "$value", val);
}
#define PYTHON_ENUM(x) \
        %typemap(enum_realname) int "x"; \
        %pythoncode %{ \
        x = _test.x\
        %} \
        enum x

%include "test.h"

这会在中间模块中为每个具有键/值对的枚举创建一个 PyDict。还有一些%pythoncode胶水可以将中间模块中的 PyDict 绑定到暴露的模块中。(我不确定如何在其中按名称引用中间模块,除了硬编码为 _test - 根据需要更改)。

这足以让我将其用作:

Python 2.7.3 (default, Aug  1 2012, 05:16:07) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> print test.SomeOtherName
{'woof': 0, 'moo': 1}
>>> print test.TestName
{'foo': 1, 'bar': 2}
>>> 
于 2012-11-18T16:39:24.977 回答
2

我很确定您正在寻找的是...
typemaps:由于类型处理对于包装器代码生成非常重要,因此 SWIG 允许用户完全定义(或重新定义)它。为此,使用了一个特殊的 %typemap 指令。(SWIG Doc2.0)

对于你可能需要的关于类型映射的所有信息,这里是 SWIG 文档的链接。 http://www.swig.org/Doc2.0/Typemaps.html#Typemaps_nn2

类型图应该允许你告诉 SWIG 将 c++ 枚举转换为你想要的 python 对象。

于 2012-11-15T21:57:07.057 回答