在Python中创建SWIG枚举
SWIG enumeration creation in Python followup
在研究如何使用swig在Python中很好地包装枚举时,我得到了这个答案。
我正在尝试创建这样的枚举:
#ifndef PYTHON_ENUM
#define PYTHON_ENUM(x) enum x
#endif
PYTHON_ENUM(TestName) {
foo=1,
bar=2
};
PYTHON_ENUM(SomeOtherName) {
woof,
moo
};
我像一样使用.I文件
%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"
问题是这引发AttributeError:模块"_test"没有属性"TestName"这源于这样一个事实,即生成的test.py定义了TestName字典:
TestName = _test.testEnum # This should be in the last line
_test.foo_swigconstant(_test)
foo = _test.foo
_test.bar_swigconstant(_test)
bar = _test.bar
在调用TestName = _test.testEnum
时,_test没有testEnum
成员,并抛出异常。一旦运行了foo_swigconstant()
或bar_swigconstant()
,就会生成_test.testEnum
,并且TestName = _test.testEnum
不会失败。因此,这一行应该在枚举值注册之后。如果我用手做,它会起作用,但每次SWIG运行时我都必须这样做,这有点麻烦。其他枚举也是如此。我可以更改接口文件以适应它吗?
我没有看到这个错误。我编译并链接了如下示例:
swig3.0 -c++ -python test.i
g++ -c -fPIC test_wrap.cxx -I/usr/include/python2.7
g++ -shared -g test_wrap.o -o _test.so
然后它就完全按照Flexo的建议工作了。请注意,生成的test.py和_test.so位于同一目录中。我在Debian下使用Python 2.7.6和SWIG 3.0.7。
我使用VS2013和SWIG 3.0.8进行了同样的尝试。结果是typemap(constcode)
生成函数woof_swigconstant
等,而不是插入const代码,后者只是公开静态字典。你用SWIG 3.0.7试过这个吗?
我仔细看了一下。使用SWIG 3.0.8和VS2013。例如foo条目的生成代码是:
SWIGINTERN PyObject *foo_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *module;
PyObject *d;
if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
d = PyModule_GetDict(module);
if (!d) return NULL;
{
PyObject *val = PyInt_FromLong((int)(foo));
SWIG_Python_SetConstant(d, "foo", val);
const char *name = "TestName";
PyObject *e = PyDict_GetItemString(d, name);
if (!e) PyDict_SetItemString(d, name, e = PyDict_New());
PyDict_SetItemString(e, "foo", val);
}
return SWIG_Py_Void();
}
因此,生成了一个函数条目。在Debian上使用SWIG 3.0.7和Python 2.7.6,我得到了以下
{
PyObject *val = PyInt_FromLong((int)(foo));
SWIG_Python_SetConstant(d, "foo", val);
const char *name = "TestName";
PyObject *e = PyDict_GetItemString(d, name);
if (!e) PyDict_SetItemString(d, name, e = PyDict_New());
PyDict_SetItemString(e, "foo", val);
}
紧接在CCD_ 9之后插入。我相信SWIG 3.0.7到3.0.8有些变化。
- 不带大括号的枚举形式
- 枚举环境变量的惯用C++14/C++17方法
- 类似枚举的计算常量
- 如何正确实现和访问运算符的各种自定义枚举器
- 错误:从"int"到枚举c++的转换无效
- C++中构造函数中的枚举
- 访问在 C++ 结构中声明的枚举变量
- 枚举类'classname'的多重定义
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- typedef 枚举和枚举类有什么区别?
- 为什么我的开关/机箱在使用枚举时默认?
- 标准::可选枚举的比较运算符
- SWIG和C++枚举类
- 相同的枚举项在 SWIG > 2.0.1 中包装在不同类型的常量中
- SWIG-将C++枚举转换为Python枚举
- SWIG:将枚举包装为 C#
- 如何使用 SWIG 枚举枚举成员
- 在Python中创建SWIG枚举
- 在类中包含枚举,而不包括 SWIG
- 如何在SWIG Java目标中包装对枚举的所有引用