我可以将C++ enum
作为真实实体而不是一组常量公开给SWIG,以便我可以在Python代码中枚举它们?如何使用SWIG枚举枚举成员
回答
我面临同样的问题。我希望SWIG很快支持C++ 11的enum class
。
下面是说服夜风把枚举结构中的一个黑客:
#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%重命名使枚举在SWIG包装器中具有相同的名称。
在Python中,你可以用一点代码枚举值:
def values(enum):
return [(k,v) for k,v in vars(enum).items() if isinstance(v,int)]
这不是漂亮,我喜欢看到一个更好的解决方案。
我敢肯定,你要找的是...
typemaps:由于类型的处理是如此重要的包装代码生成,SWIG使得它能够被用户完全定义(或重定义)。为此,使用特殊的%typemap指令。 (SWIG Doc2.0)
对于您可能需要的有关typemaps的所有信息,请参阅SWIG文档的链接。 http://www.swig.org/Doc2.0/Typemaps.html#Typemaps_nn2
Typemaps应该允许您告诉SWIG将C++枚举转换为您想要的python对象。
@Flexo,tbh,我不知道类型图,我是SWIG的新手,他们只是在项目的一些较暗的部分使用它,它工作,没有人关心,但后来我决定扩展它位。 – unkulunkulu
我们可以做一些让你在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模块中为enum注入一些额外的东西,但我们需要知道枚举的名称来完成此操作; 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}
>>>
所以看起来这很难,因为SWIG的目的很简单,似乎他们没有考虑将C/C++反射带入脚本语言,只是界面生成。看起来我不得不采用Mark Tolonen的解决方案,因为很少有人会理解你的,尽管我现在正在理解它:D谢谢你尝试使用类型映射的例子。 – unkulunkulu
@unkulunkulu - 通常SWIG会尽力让您在C(或C++)中尽可能做到尽可能简单,但除此之外,这往往会更困难。 – Flexo
@Flexo尼斯解决方案。我扩展了一下导入一个字典,它支持键完成,并用'x = dotdict(_test.x)'替换'x = _test.x'并添加了一个'%pythoncode%{from dicts import dotdict% }在'PYTHON_ENUM'宏之前。 –
- 1. 枚举成员
- 2. 如何从枚举成员
- 3. Jave枚举成员
- 4. Python枚举类成员
- 5. 枚举结构的成员?
- 6. 枚举和指向成员
- 7. 查找未使用的枚举成员
- 8. 使用列枚举的LINQ表枚举
- 9. 如何在保持枚举枚举
- 10. #define枚举或如何扩展枚举
- 11. 如何枚举嵌套枚举器
- 12. 如何枚举Objective-C中的枚举?
- 13. 生成枚举
- 14. 使用枚举
- 15. 使用枚举
- 16. 使用枚举
- 17. 使用枚举
- 18. 转换枚举来枚举
- 19. 枚举的枚举[JAVA]
- 20. 带枚举的MySQL枚举
- 21. Java类枚举枚举类
- 22. 重新枚举枚举
- 23. Java枚举找到枚举
- 24. 在枚举中枚举
- 25. 使用JavaPoet生成枚举
- 26. 如何在枚举类型中定义枚举成员的映射?
- 27. 任何方式来枚举类成员?
- 28. 如何使用枚举值?
- 29. 如何使用枚举?
- 30. 如何使用枚举? java
是啊,我在想这样的事情,但你的答案提供了一些准备使用的图案,谢谢。你能解释一下上面提到的'sizeof'问题吗?什么代码可以完全打破,因为我不太明白。 – unkulunkulu
我将删除该部分。这是我在试图找到实现时正在考虑的事情,但我只是重新访问它,并不是一个真正的问题。 –